C++中的三种继承方式
1,被忽略的细节:
1,冒号( :)表示继承关系,parent 表示被继承的类,public 的意义是什么?
1 class parent 2 { 3 4 }; 5 6 class child : public parent 7 { 8 9 };
2,有趣的问题:
1,是否可以将继承语句中的 public 换成 protected 或者 private?如果可以,与 public 继承有什么区别?
3,有趣的尝试编程实验:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class parent 7 { 8 }; 9 10 class child_a : public parent 11 { 12 }; 13 14 class child_b : protected parent 15 { 16 }; 17 18 class child_c : private parent 19 { 20 }; 21 22 int main() 23 { 24 return 0; 25 }
1,protected 和 private 地位对等,推理的角度可以过,实际的编译结果也是同样的结论;
2,本文主要分析这三种继承方式有何不同;
4,不同的继承方式(这是父类成员在子类中被外界访问的级别):
1,c++ 中支持三种不同的继承方式;
1,public 继承:
1,父类成员在子类中保持原有访问级别;
2,private 继承:
1,父类成员在子类中变为私有成员;
3,protected 继承:
1,父类中的公有成员变为保护成员,其它成员保持不变;
2,继承成员的属性:
1,max{继承方式,父类成员访问属性};
2,c++ 中的默认继承方式为 private;
3,继承与访问级别深度实践编程实验:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class parent 7 { 8 protected: 9 int m_a; 10 protected: 11 int m_b; 12 public: 13 int m_c; 14 15 void set(int a, int b, int c) 16 { 17 m_a = a; 18 m_b = b; 19 m_c = c; 20 } 21 }; 22 23 class child_a : public parent 24 { 25 public: 26 void print() 27 { 28 cout << "m_a" << m_a << endl; 29 cout << "m_b" << m_b << endl; 30 cout << "m_c" << m_c << endl; 31 } 32 }; 33 34 class child_b : protected parent 35 { 36 public: 37 void print() 38 { 39 cout << "m_a" << m_a << endl; 40 cout << "m_b" << m_b << endl; 41 cout << "m_c" << m_c << endl; 42 } 43 }; 44 45 class child_c : private parent 46 { 47 public: 48 void print() 49 { 50 cout << "m_a" << m_a << endl; 51 cout << "m_b" << m_b << endl; 52 cout << "m_c" << m_c << endl; 53 } 54 }; 55 56 int main() 57 { 58 child_a a; 59 child_b b; 60 child_c c; 61 62 a.m_c = 100; 63 // b.m_c = 100; // child_b 保护继承自 parent, 所以所有 public 成员全部变成了 protected 成员, 因此外界无法访问; 64 // c.m_c = 100; // child_c 私有继承自 parent, 所以所有的成员全部变成了 private 成员, 因此外界无法访问; 65 66 a.set(1, 1, 1); 67 // b.set(2, 2, 2); // 保护继承; 68 // c.set(3, 3, 3); // 私有继承; 69 70 a.print(); // 继承方式只影响继承自父类成员的访问方式,外界访问子类方式无影响; 71 b.print(); // 继承方式只影响继承自父类成员的访问方式,外界访问子类方式无影响; 72 c.print(); // 继承方式只影响继承自父类成员的访问方式,外界访问子类方式无影响; 73 74 return 0; 75 }
1,父类中的访问级别影响着子类的访问,但是继承级别不影响子类的访问、影响其它外部类访问父类中的成员;
5,遗憾的事实:
1,一般而言,大型的 c++ 工程项目中只使用 public 继承;
1,这已经足够了;
2,保护继承和私有继承根本就没什么用;
2,c++ 的派生语言只支持一种继承方式(public 继承);
1,java、c# 等语言只有一种继承方式即 public 继承方式;
3,protected 和 private 继承带来的复杂性远大于实用性;
1,仅在学术研究领域研究;
6,c++ 派生语言初探编程实验:
1,d 语言(在 linux 中用 gdc 编译,生成 *.out 文件):
1 module d_demo; // 将下面的所有代码定义为模块,模块名字为 2 d_demo; 3 4 import std.stdio; // import 同 include 5 import std.string; // import 同 include 6 7 class obj // 这里定义了一个 obj 类 8 { 9 protected: 10 string mname; 11 string minfo; 12 13 public: 14 this() // 这是 d 语言中的构造函数,d 语言中的构造函数统一的用 this 这个关键字表示,由 c++ 进化而来; 15 { 16 mname = "object"; 17 minfo = ""; 18 } 19 20 string name() // 定义两个成员函数; 21 { 22 return mname; 23 } 24 25 string info() 26 { 27 return minfo; 28 } 29 } 30 31 class point : obj // 定义了一个类 point,其继承自 obj,d 语言中的继承方式默认的是 public 继承; 32 { 33 private: 34 int mx; 35 int my; 36 37 public: 38 this(int x, int y) 39 { 40 mx = x; 41 my = y; 42 mname = "point"; 43 minfo = format("p(%d, %d)", mx, my); // 和 c 语言中的语法规则一样; 44 } 45 46 int x() 47 { 48 return mx; 49 } 50 51 int y() 52 { 53 return my; 54 } 55 } 56 57 void main(string[] args) // 程序运行的入口; 58 { 59 writefln("d demo"); // d demo;打印语句之后空一行,同 printf; 60 61 point p = new point(1, 2); // 动态生成 point 对象; 62 63 writefln(p.name()); // point,公有继承; 64 writefln(p.info()); // p(1, 2),公有继承; 65 }
1,没学过 d 语言,但是要读懂 d 语言的代码是比较容易的;
2,如果因工作需要要学习 d 语言程序设计,将是轻而易举的事情;
2,c# 语言(linux 中用 gmcs 编译,生成 *.exe 文件):
1 class obj // 定义一个类 obj; 2 { 3 protected string mname; // 访问属性 protected; 4 protected string minfo; 5 6 public obj() // 无返回值,函数名同类名,即构造函数,访问属性为 public; 7 { 8 mname = "object"; 9 minfo = ""; 10 } 11 12 public string name() 13 { 14 return mname; 15 } 16 17 public string info() 18 { 19 return minfo; 20 } 21 } 22 23 class point : obj // 定义一个类 point,继承自 obj,只有一种 public 继承方式; 24 { 25 26 private int mx; 27 private int my; 28 29 public point(int x, int y) // 构造函数; 30 { 31 mx = x; 32 my = y; 33 mname = "point"; 34 minfo = "p(" + mx + ", " + my + ")"; // 通过 + 操作符来连接字符串和整型变量,最终得到一个字符串;c++ 中可以通过重载全局的 + 操作符就能够连接一个字符串和一个整型变量最终得到一个字符串,别的语言中的特性,不明白的话,考虑下在 c++ 中如何实现; 35 } 36 37 public int x() 38 { 39 return mx; 40 } 41 42 public int y() 43 { 44 return my; 45 } 46 } 47 48 class program 49 { 50 public static void main(string[] args) // 程序入口 51 { 52 system.console.writeline("c# demo"); // c# demo 53 54 point p = new point(1, 2); 55 56 system.console.writeline(p.name()); // point 57 system.console.writeline(p.info()); // p(1, 2) 58 59 } 60 }
3,java 程序:
1 class obj 2 { 3 protected string mname; 4 protected string minfo; 5 6 public obj() 7 { 8 mname = "object"; 9 minfo = ""; 10 } 11 12 public string name() 13 { 14 return mname; 15 } 16 17 public string info() 18 { 19 return minfo; 20 } 21 } 22 23 class point extends obj // extends 表示公有继承,更加直观; 24 { 25 26 private int mx; 27 private int my; 28 29 public point(int x, int y) 30 { 31 mx = x; 32 my = y; 33 mname = "point"; 34 minfo = "p(" + mx + ", " + my + ")"; 35 } 36 37 public int x() 38 { 39 return mx; 40 } 41 42 public int y() 43 { 44 return my; 45 } 46 } 47 48 class program { 49 public static void main(string[] args){ // 程序运行如口 50 system.out.println("java demo"); // java demo 51 52 point p = new point(1, 2); 53 54 system.out.println(p.name()); // point 55 system.out.println(p.info()); // p(1, 2) 56 } 57 }
1,现在已经有能力读懂 d、c#、java 语言程序了;
1,c#、java 可以从事网络开发、游戏开发;
2,d 语言可以从事系统开发;
2,工程里面,仅仅使用 public 继承就够了;
7,小结:
1,c++ 中支持 3 种不同的继承方式;
2,继承方式直接影响父类成员在子类中的访问属性;
3,一般而言,工程中只使用 public 的继承方式;
4,c++ 的派生语言中只支持 public 继承方式;
上一篇: C++中组合和继承的概念及意义
下一篇: 单元测试JUnit