二、面向对象之继承
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class News { public: void header() { cout << "公共头部" << endl; } void footer() { cout << "公共底部" << endl; } void left() { cout << "左侧列表" << endl; } void content() { cout << "新闻播报" << endl; } }; class YULE { public: void header() { cout << "公共头部" << endl; } void footer() { cout << "公共底部" << endl; } void left() { cout << "左侧列表" << endl; } void content() { cout << "娱乐八卦" << endl; } }; void test() { News news; news.header(); news.footer(); news.left(); news.content(); YULE yule; yule.header(); yule.footer(); yule.left(); yule.content(); } int main() { test(); return EXIT_SUCCESS; } // 代码重复率太高,冗余大
// 设置基类,解决冗余的问题 #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; // 继承类的写法 // 抽象一个 基类的网页 重复的代码都写在这个网页上 class BasePage { public: void header() { cout << "公共头部" << endl; } void footer() { cout << "公共底部" << endl; } void left() { cout << "左侧列表" << endl; } }; class News :public BasePage // News 类继承 BasePage 类 { public: void content() { cout << "新闻播报" << endl; } }; class YULE:public BasePage // YULE 类继承 BasePage 类 { public: void content() { cout << "娱乐八卦" << endl; } }; void test() { News news; news.header(); news.footer(); news.left(); news.content(); YULE yule; yule.header(); yule.footer(); yule.left(); yule.content(); } int main() { test(); return EXIT_SUCCESS; }
public: 共有继承
protected:保护继承
private: 私有继承
不管公有继承、私有继承、保护继承, 基类中的私有属性, 都不可以继承下去
公有继承 public:
父类中的public 在子类中的是public
父类中的protected 在子类中的是protected
保护继承 protected:
父类中的public 在子类中的是protected
父类中的protected 在子类中的是protected
私有继承 private:
父类中的public 在子类中的是private
父类中的protected 在子类中的是private
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class Base1 { public: int a; protected: int b; private: int c; }; // 共有继承 class Son1 : public Base1 { public: void func() { cout << a << endl; // 基类中共有属性可以继承,还是 public cout << b << endl; // 基类中保护属性可以继承, 还是 protected //cout << c << endl; // 基类中私有属性不可继承 } }; // 保护继承 class Son2 : protected Base1 { public: void func() { cout << a << endl; // 基类中共有属性可以继承,但是 protected cout << b << endl; // 基类中保护属性可以继承, 还是 protected //cout << c << endl; // 基类中私有属性不可继承 } }; // 私有继承 class Son3 : private Base1 { public: void func() { cout << a << endl; // 基类中共有属性可以继承,但是 private cout << b << endl; // 基类中保护属性可以继承, 还是 private //cout << c << endl; // 基类中私有属性不可继承 } }; class GrandSon :public Son3 { public: void func() { //cout << a << endl; 访问不到, 因为到Son3中, a已经是私有的了 } }; void myFunc() { Son1 s1; s1.a; Son2 s2; // s2.a; 类外不能访问 protected Son3 s3; // s3.a; 类外不能访问 private } int main() { return EXIT_SUCCESS; }
/* 子类会继承父类中所有的内容, 包括私有属性,只是我们访问不到,编译器给隐藏了 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class BaseClass { public: int A; protected: int B; private: int C; }; // 在子类中会继承父类的私有成员,只是被编译器被隐藏起来,所以访问不到私有成员 class Son : public BaseClass { public: int D; }; void test() { cout << sizeof(Son) << endl; // 16, 子类会继承父类的私有成员,但是不能用 } int main() { test(); return EXIT_SUCCESS; }
/* 子类创建对象时,先调用父类的构造,在调用自身构造, 析构的顺序正好相反 子类会继承父类的成员属性和成员函数,但是不会继承父类的构造函数和析构函数 如果父类中没有合适的默认构造,子类可以用初始化列表的方式显示的调用父类的其他构造。 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class BaseClass { public: BaseClass() { cout << "Base的默认构造调用" << endl; } ~BaseClass() { cout << "Base的的析构函数调用" << endl; } }; class Son : public BaseClass { public: Son() { cout << "Son的默认构造调用" << endl; } ~Son() { cout << "Son的的析构函数调用" << endl; } }; class GrandSon : public Son { public: GrandSon() { cout << "GrandSon的默认构造调用" << endl; } ~GrandSon() { cout << "GrandSon的的析构函数调用" << endl; } }; // 子类会继承父类的成员属性和成员函数,但是不会继承父类的构造函数和析构函数 void test() { GrandSon g1; /* Base的默认构造调用 Son的默认构造调用 GrandSon的默认构造调用 GrandSon的的析构函数调用 Son的的析构函数调用 Base的的析构函数调用 */ } class BaseClass2 { public: BaseClass2(int a) { this->A = a; cout << "BaseClass2有参构造调用" << endl; } int A; }; class Son2 : public BaseClass2 { public: //Son2() // 直接这样会报错,因为一开始就会先调用父类中不存在默认构造了 //{ //} Son2(int a) : BaseClass2(a) // 利用初始化列表方法显示调用 有参构造 { } }; void test02() { Son2 son2(100); } int main() { test(); return EXIT_SUCCESS; }
/* 如果子类和父类拥有同名的函数、属性,子类不会覆盖父类的成员属性和成员函数 如果子类与父类的成员函数名称相同,子类会把父类的所有的同名的版本都隐藏, 想要调用父类的,需要加作用域 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class BaseClass { public: BaseClass() { this->A = 100; } void func() { cout << "父类的func无参调用" << endl; } void func(int a) { cout << "父类的func有参调用" << endl; } void func2() { cout << "父类的func2无参调用" << endl; } void func2(int a) { cout << "父类的func2有参调用" << endl; } int A; }; class Son : public BaseClass { public: Son() { this->A = 200; } void func() { cout << "Son的func调用" << endl; } int A; }; // 如果子类和父类拥有同名的函数、属性,子类不会覆盖父类的成员属性和成员函数 // 如果子类与父类的成员函数名称相同,子类会把父类的所有的同名的版本都隐藏, 想要调用父类的,需要加作用域 void test() { Son s1; cout << "s1.A = " << s1.A << endl; // s1.A = 200 // 想调用父类的A cout << "父类的A = " << s1.BaseClass::A << endl; // 父类的A = 100 s1.func(); // Son的func调用 //s1.func(2); // 不能直接调用 s1.BaseClass::func(); // 父类的func无参调用 s1.func2(); // 父类的func2无参调用 , 子类没有,直接调用父类的方法 s1.func2(2); // 父类的func2有参调用 } int main() { test(); return EXIT_SUCCESS; }
/* 类似非静态成员处理, 想要访问父类的成员, 加上作用域 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class BaseClass { public: static void func() { cout << "base的func" << endl; } static void func(int a) { cout << "base的func(int)" << endl; } static int A; }; class Son : public BaseClass { }; class Son2 : public BaseClass { public: static void func() { cout << "Son2的func" << endl; } static void func(int a) { cout << "Son2的func(int)" << endl; } static int A; }; int BaseClass::A = 10; // 类内声明,类外调用 int Son2::A = 20; // 子类可以继承父类的静态变量 void test() { cout << Son::A << endl; // 10 cout << Son2::A << endl; // 20 // 访问Son2的父类的A cout << BaseClass::A << endl; // 10 Son2::func(); // Son2的func // 访问父类的同名函数 BaseClass::func(); // base的func Son2::BaseClass::func(10); // base的func(int) } int main() { test(); return EXIT_SUCCESS; }
七、多继承与菱形继承
/* 多继容易出现二义性, 通过调用作用域可以解决 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class Base1 { public: Base1() { this->A = 10; } int A; }; class Base2 { public: Base2() { this->B = 20; } int B; }; // 多继容易出现二义性, 通过调用作用域可以解决 class Son : public Base1, public Base2 { public: int C; int D; }; void test() { cout << sizeof(Son) << endl; // 16 Son s1; cout << "s1.A = " << s1.A << endl; //10 cout << "s1.B = " << s1.B << endl; // 20 } int main() { test(); return EXIT_SUCCESS; }
7.2 菱形继承与虚继承
/* SheepTuo 同时继承了 Sheep, Tuo。 这两个父类都存在 Age, SheepTuo自己使用的使用只需要一个 Age就行了,所以 SheepTuo就会多开辟了一些没必要空间 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class Animal { public: int Age; }; class Sheep : public Animal { public: }; class Tuo : public Animal { public: }; // SheepTuo 同时继承了 Sheep, Tuo。 这两个父类都存在 Age, SheepTuo自己使用的使用只需要一个 Age就行了,所以 SheepTuo就会多开辟了一些没必要空间 // 菱形继承的解决方案: 虚继承 class SheepTuo : public Sheep, public Tuo { public: }; void test() { SheepTuo st; st.Sheep::Age = 10; st.Tuo::Age = 20; cout << st.Sheep::Age << endl; cout << st.Tuo::Age << endl; } int main() { test(); return EXIT_SUCCESS; }
/* 在继承的类前面加上 virtual */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> using namespace std; class Animal { public: int Age; }; // 虚基类 Sheep class Sheep :virtual public Animal { public: }; // 虚基类 Tuo class Tuo :virtual public Animal { public: }; // SheepTuo 同时继承了 Sheep, Tuo。 这两个父类都存在 Age, SheepTuo自己使用的使用只需要一个 Age就行了,所以 SheepTuo就会多开辟了一些没必要空间 // 菱形继承的解决方案: 虚继承 class SheepTuo : public Sheep, public Tuo { public: }; void test() { SheepTuo st; st.Sheep::Age = 10; st.Tuo::Age = 20; // 因为是虚基类, 所以操作的是同一个 Age,所以结果应该是一样的 cout << st.Sheep::Age << endl; // 20 cout << st.Tuo::Age << endl; // 20 cout << st.Age << endl; // 20 同时也可以直接访问了,没有二义性的可能了 } int main() { test(); return EXIT_SUCCESS; }