最近在学习 C++,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习C++的童鞋们提供一份参考。
继承和多态是面向对象语言最强大的功能。有了继承和多态,我们可以完成代码重用。在C中有许多技巧可以实现多态。本文的目的就是演示一种简单和容易的技术,在C中应用继承和多态。通过创建一个VTable(virtual table)和在基类和派生类对象之间提供正确的访问,我们能在C中实现继承和多态。VTable能通过维护一张函数表指针表来实现。为了提供基类和派生类对象之间的访问,我们可以在基类中维护派生类的引用和在派生类中维护基类的引用。
继承
类关系
访问控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <iostream> using namespace std;
class Test { public: int c; protected: int b; private: int a; };
class Parent { public: Parent(int a = 1, int b = 2, int c = 3) { this->a = a; this->c = c; this->b = b; } void PrintSelf() { cout << "Hello" << endl; } int c; protected: int b; private: int a; };
class Child : public Parent { public: void Print() { cout << a << endl; cout << c << endl; cout << b << endl; } protected: private: };
int main() { Child c1; c1.c = 10; c1.Print(); c1.PrintSelf(); system("pause"); return 0; }
|
继承方式
Demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <iostream> using namespace std;
#include <cstdlib>
class A { private: int a; protected: int b; public: int c;
A() { a = 0; b = 0; c = 0; }
void set(int a, int b, int c) { this->a = a; this->b = b; this->c = c; } };
class B : public A { public: void print() { cout << "b = " << b; cout << "c = " << endl; } };
class C : protected A { public: void print() { cout << "b = " << b; cout << "c = " << endl; } };
class D : private A { public: void print() { cout << "b = " << b << endl; cout << "c = " << c << endl; } };
int main() {
A aa; B bb; C cc; D dd;
aa.c = 100; bb.c = 100;
aa.set(1, 2, 3); bb.set(10, 20, 30);
bb.print(); cc.print(); dd.print();
system("pause"); return 0; }
|
继承中的构造析构
赋值兼容性
可以把子类对象赋值给基类指针,子类就是一种特殊的父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| #include <iostream> using namespace std;
class Parent { public: Parent(); ~Parent(); void Print(); private: protected: int a; int b; };
Parent::Parent() { }
Parent::~Parent() { }
void Parent::Print() { cout << "父类" << endl; }
class Child : public Parent { public: Child(); ~Child(); void Print(); private: int c; };
Child::Child() { a = 0; b = 0; c = 0; }
Child::~Child() { }
void Child::Print() { cout << "子类" << endl; }
void howToPoint(Parent *base) { base->Print(); }
void howToPoint_Test01(Parent &base) { base.Print(); }
void howToPoint_Test(Child *base) { base->Print(); }
void howToPoint_Test02(Child &base) { base.Print(); }
void main() { Child c1; Parent p1; c1.Print(); p1.Print(); Parent *base = NULL; base = &c1; base->Print();
Parent &base1 = c1; base1.Print();
howToPoint(&c1); howToPoint(&p1);
howToPoint_Test01(c1); howToPoint_Test01(p1);
howToPoint_Test(&c1); howToPoint_Test((Child *)&p1);
howToPoint_Test02(c1); howToPoint_Test02((Child &)p1);
Parent p3 = c1; system("pause"); }
|
- 子类对象可以当作父类对象使用
- 子类对象可以直接赋值给父类对象
- 子类对象可以直接初始化父类对象
- 父类指针可以直接指向子类对象
- 父类引用可以直接引用子类对象
继承中的对象模型
- 在子类对象构造的时候,需要调用父类构造函数对其继承得来的成员进行初始化
- 在子类对象析构的时候,需要调用父类析构函数对其继承的来的成员进行清理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <iostream> using namespace std;
class Parent { public: Parent() { cout << "父类构造函数" << endl; } void PrintP() { printf("我是父类\n"); } protected: int a, b; private: };
class Child : public Parent { public: Child() { a = 0; b = 0; c = 0; cout << "子类构造函数" << endl; } void PrintC() { printf("我是子类\n"); } protected: private: int c; };
void howToPrint(Parent *p) { p->PrintP(); }
void howToPrint1(Parent &p) { p.PrintP(); }
int main() { Parent p1; Child c1; system("pause"); return 0; }
|
继承中有有参构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <iostream> using namespace std;
class Parent { public: Parent(char *p) { cout << "父类构造函数" << endl; } void PrintP() { printf("我是父类\n"); }
protected: int a, b; private:
};
class Child : public Parent { public: Child() :Parent("sYstemk1t") { a = 0; b = 0; c = 0; cout << "子类构造函数" << endl; } void PrintC() { printf("我是子类\n"); } protected: private: int c; };
int main() { Parent p1("sYstemk1t"); system("pause"); return 0; }
|
继承中的同名问题
同名变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> using namespace std;
class A { public: int a, b; void Print() { cout << "我是父类" << endl; cout << a << endl; } protected: private: };
class B : public A { public: int a, b; protected: private:
};
void main() { B b1; b1.a = 10; b1.b = 20;
b1.A::a = 20; b1.A::Print(); system("pause"); }
|
同名函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <iostream> using namespace std;
class A { public: int a, b; void PrintA() { cout << "我是父类" << endl; cout << a << endl; } void Print() { cout << "我是父类的A" << endl; } protected: private: };
class B : public A { public: int a, b;
void Print() { cout << "我是子类的A" << endl; } protected: private:
};
void main() { B b1; b1.a = 10; b1.b = 20;
b1.A::a = 20; b1.A::PrintA();
b1.A::Print(); b1.Print(); system("pause"); }
|
派生类中的静态成员
- 基类定义的静态成员,将被所有派生类共享
- 根据静态成员自身的访问特性和派生类的集成方式,在类层次体系中具有不同的访问性质
静态成员
类中,静态成员变量被所有类的对象共享,(共享就是即使类的其中一个对象修改了该静态成员变量,那么类的其他所有对象再访问该静态成员变量时,就是修改后的值),所以可以认为该静态成员变量是属于该类的,而不属于某一个对象,且需要在类外被初始化,编译时就被创建并初始化;
静态成员函数只会被调用一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> using namespace std;
class A { public: A() { a = 10; } static int a; int b; void PrintA() { cout << "我是父类" << endl; cout << a << endl; } void Print() { cout << "我是父类的A" << endl; cout << a << endl; } protected: private: };
int A::a = 0;
class B : private A { public: int b,c;
void Print() { cout << "我是子类的A" << endl; cout << a << endl; } protected: private:
};
void main() { B b1; b1.Print(); system("pause"); }
|
多继承
一个类有多个直接基类的继承关系称为多继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <iostream> using namespace std;
class Base1 { public: Base1() { b1 = 1; } int b1; protected: private:
};
class Base2 { public: Base2() { b2 = 2; } int b2;
protected: private:
};
class Child : public Base1,public Base2 { public: Child() { ; } void PrintB() { cout << b1 << endl; cout << b2 << endl; } protected:
private:
};
int main() { Child c1; c1.PrintB(); system("pause"); return 0; }
|
虚基类
多继承会产生二义性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream> using namespace std; class B { public: int i; private: protected: };
class B1 : virtual public B { public: int b1; private: protected: };
class B2 : virtual public B { public: int b2; private: protected: };
class C : public B1,public B2 { public: private: protected: };
void main() { C c1; c1.b1 = 10; c1.b2 = 20; c1.i = 30; system("pause"); }
|