面向对象程序设计(Object-oriented programming)的核心思想是数据抽象,继承,和动态绑定。
在C++语言中,基类将类型相关的函数与派生类不做改变直接继承的函数区分对待。对于某些函数,基类希望它的派生类各自定义适合自身的版本,此时基类就将这些函数声明成虚函数(virtual function)。
1 class Quote { 2 public: 3 std::string isbn() const; 4 virtual double net_price(std::size_t n) const; 5 };
派生类必须通过使用派生列表(class derivation list)明确指出它是从哪个(哪些)基类继承而来的:
如下:
1 class Bulk_quote : public Quote { 2 public: 3 double net_price(std::size_t) const override; 4 };
派生类必须在其内部对所有重新定义的虚函数进行声明。派生类可以在这样的函数之前加上virtual关键字,但是并不是非得这么做。并且,C++11新标准允许派生类显式地注明它将使用哪个成员函数改写基类的虚函数,具体措施是在改函数的形参列表之后增加一个override关键字。
1 #include<iostream> 2 class A { 3 public: 4 int p = 0; 5 virtual void test(); 6 private: int p2 = 1; 7 protected: int p3 = 2; 8 }; 9 10 void A::test() 11 { 12 std::cout << this->p << this->p2 << this->p3 << std::endl; 13 } 14 15 class B:public A { 16 public: 17 int b = 3; 18 void test() { 19 std::cout << this->b << this->b2 << this->b3 << std::endl; 20 } 21 22 void test2() { 23 std::cout << this->p3 << std::endl; // 派生类可以访问基类的protect和public 24 } 25 26 friend void test3() { 27 std::cout << this-> << std::endl; 28 } 29 private: int b2 = 4; 30 protected: int b3 = 5; 31 }; 32 33 int main() 34 { 35 A a; 36 std::cout << a.p << std::endl;// 只能访问自己的public 37 a.test(); 38 39 B b; 40 std::cout << b.b << b.p << std::endl;// 派生类 只能访问自己的puiblic和基类的public 41 b.test(); 42 43 }
在C++语言中,当我们使用基类的引用(或指针)调用一个虚函数时将发生动态绑定。明晰派生类调用到底调用谁的print方法。
比如:
1 #include<iostream> 2 class A { 3 public: 4 A() = default; 5 virtual void print() { 6 std::cout << "a" << std::endl; 7 } 8 virtual ~A() { 9 std::cout << "destroy A" << std::endl; 10 }; 11 }; 12 13 class B :public A { 14 public: 15 B() = default; 16 void print() { 17 std::cout << "b" << std::endl; 18 } 19 ~B() { 20 std::cout << "destroy B" << std::endl; 21 } 22 23 }; 24 25 int main() 26 { 27 A a; 28 B b; 29 a.print(); 30 b.print(); 31 32 /// 动态绑定.如果基类中 print 方法不是虚函数,则以下结果均为a 33 A *a2 = &a; 34 A *b2 = &b; 35 a2->print();// a 36 b2->print();// b 37 38 A &a3 = a; 39 A &b3 = b; 40 a3.print();// a 41 b3.print();// b 42 43 /// 强行调用基类 44 //b.A::print(); // a 45 //b2->A::print(); // a 46 //b3.A::print(); // a 47 48 }
原文:https://www.cnblogs.com/KongHuZi/p/11530992.html