关于c++:类和对象

53次阅读

共计 9931 个字符,预计需要花费 25 分钟才能阅读完成。

类和类型

** 类型 ** 变量
int a;
long long b;
char c;
double d;
float e;
类  对象
Cat  cat; 栈空间,编译器保护
Cat * ptr_cat = new cat(); 堆空间,程序员本人保护

内存区:代码区 常量区,堆,栈
一个类在内存中须要占多大的内存空间呢:是由成员变量的动态属性决定的,还有一个额定的因素占用内存空间:虚办法(TODO)编译器主动创立一个八字节的虚函数表,是链表的构造
1231123

内存对齐

内存对齐基本上是通明的,这是编译器该干的活,编译器为程序中的每个数据单元安顿在适合的地位上,从而导致了雷同的变量,不同申明程序的构造体大小的不同。
缩小不必要的内存开销,int 放在一起 double 放在一起

采纳 #pragma pack(1) 解决序列化和反序列化带来的内存对齐问题 //52 个字节了,
减少成员办法不影响类对象的内存大小(虚办法除外), 为什么要这么设计呢?成员办法存在代码段的,


class People{
string name;
int age;
double height;
double weight;
};//56 个字节 // 加上一行后变成了 52 对齐

class People{
string name;
int age;
double height;
double weight;
int children;
};//64 个字节

class People{
string name;
int age;
int children;
double height;
double weight;
void say(string word);
};//56 个字节
编译后存在内存中 say 变成了 void say(People * this, string word);

类封装

class 默认 private,struct 默认 public

私有继承(public)

私有继承在 C ++ 中是最罕用的一种继承形式,咱们先来看一个示例:

 1 #include<iostream>
 2 using namespace std;
 3 class Father{
 4 public:
 5     Father()=default;
 6     void Father_show1(){
 7         cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
 8     }
 9 protected:
10     void Father_show2(){
11         cout<<"调用 Father 类的 protected 办法:Father_show2"<<endl;
12     }
13 private:
14     void Father_show3(){
15         cout<<"调用 Father 类的 private 办法:Father_show3"<<endl;
16     }
17 }; 
18 
19 class Son:public Father{
20 public:
21     Son()=default;
22     void Son_fun1(){
23         cout<<"调用 Son 类的 public 办法:Son_fun1"<<endl;
24         Father_show1();
25         Father_show2();
26         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
27     }
28 protected:
29     void Son_fun2(){
30         cout<<"调用 Son 类的 protected 办法:Son_fun2"<<endl;
31         Father_show1();
32         Father_show2();
33         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
34     }
35 private:
36     void Son_fun3(){
37         cout<<"调用 Son 类的 private 办法:Son_fun3"<<endl;
38         Father_show1();
39         Father_show2();
40         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
41     }
42 };
43 
44 int main(){
45     Son s;
46     s.Son_fun1(); // 正确,只能调用对象的 public 办法
47     s.Father_show1();
48     //s.Son_fun2(); // 谬误:不能调用对象的 protected 办法
49     //s.Father_show2();
50     //s.Son_fun3(); // 谬误:不能调用对象的 private 办法
51     //s.Father_show3();
52     return 0;
53 }

对私有继承的了解:

  1. 三种属性能力的强弱:public<protected<private
  2. 在 C ++ 的继承中,子类会继承父类中除构造函数和析构函数之外的所有成员(正所谓儿子无奈继承父亲的生死)。而私有继承(public)就相当于先将从父类那里继承的全副成员放到子类的 public 局部,如下:

     1 class Son:public Father{
     2 // 从 Father 类中继承的所有成员
     3 public:
     5         void Father_show1(){
     6             cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
     7         }
     8     protected:
  3. cout<<“ 调用 Father 类的 protected 办法:Father_show2” <<endl;}
  4. private:
  5. void Father_show1(){
  6. cout<<“ 调用 Father 类的 public 办法:Father_show1″<<endl;
  7. }
  8. public:
  9. Son()=default;
  10. void Son_fun1(){
  11. cout<<“ 调用 Son 类的 public 办法:Son_fun1″<<endl;
  12. Father_show1();
  13. Father_show2();
  14. //Father_show3();// 谬误:无奈调用 Father 类的 private 办法
  15. }
  16. protected:
  17. void Son_fun2(){
  18. cout<<“ 调用 Son 类的 protected 办法:Son_fun2″<<endl;
  19. Father_show1();
  20. Father_show2();
  21. //Father_show3();// 谬误:无奈调用 Father 类的 private 办法
  22. }
  23. private:
  24. void Son_fun3(){
  25. cout<<“ 调用 Son 类的 private 办法:Son_fun3″<<endl;
  26. Father_show1();
  27. Father_show2();
  28. //Father_show3();// 谬误:无奈调用 Father 类的 private 办法
  29. }
  30. };

而后依据三种属性能力的强弱决定成员的属性在子类中到底是 public、protected 还是 private:

• Father_show1():在 Father 类中属于 public 办法,继承到子类 Son 后放在类的 public 局部,因为 public=public,因而在子类 Son 中 Father_show1()办法仍是 public 办法

• Father_show2():在 Father 类中属于 protected 办法,继承到子类 Son 后放在类的 public 局部,因为 protected>public, 因而子类 Son 中 Father_show2()办法是 protected 办法

• Father_show3():在 Father 类中属于 private 办法,能够了解为“父亲的隐衷”,继承到子类 Son 后放在类的 public 局部,因为 private>public, 因而子类 Son 中 Father_show3()办法是 private 办法。然而正所谓“儿子即便继承了父亲的财产,也无奈通晓父亲的隐衷”,因而不论儿子以何种形式(public/protected/private)继承父亲的“财产”也无奈利用父亲的“隐衷”去进行“交易”,换句话说就是父类的 private 成员尽管能够被子类继承,但子类中的任何成员办法都不能在其函数体中调用这些从父类中继承而来的 private 成员。因而 Son 类中的成员办法不论其为与什么局部,都无奈调用 Father_show3

3. 对象只能调用其 public 局部的成员,而不能调用 protected 和 private 局部的成员。因而上例中 Son 类的对象 s 能够调用办法 Son_fun1()和办法 Father_show1(),而无奈调用办法 Son_fun2()、Son_fun3()、Father_show2()和 Father_show3()

爱护继承(protected)

将下面的示例改为爱护继承:

 1 #include<iostream>
 2 using namespace std;
 3 class Father{
 4 public:
 5     Father()=default;
 6     void Father_show1(){
 7         cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
 8     }
 9 protected:
10     void Father_show2(){
11         cout<<"调用 Father 类的 protected 办法:Father_show2"<<endl;
12     }
13 private:
14     void Father_show3(){
15         cout<<"调用 Father 类的 private 办法:Father_show3"<<endl;
16     }
17 }; 
18 
19 class Son:protected Father{
20 public:
21     Son()=default;
22     void Son_fun1(){
23         cout<<"调用 Son 类的 public 办法:Son_fun1"<<endl;
24         Father_show1();
25         Father_show2();
26         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
27     }
28 protected:
29     void Son_fun2(){
30         cout<<"调用 Son 类的 protected 办法:Son_fun2"<<endl;
31         Father_show1();
32         Father_show2();
33         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
34     }
35 private:
36     void Son_fun3(){
37         cout<<"调用 Son 类的 private 办法:Son_fun3"<<endl;
38         Father_show1();
39         Father_show2();
40         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
41     }
42 };
43 
44 int main(){
45     Son s;
46     s.Son_fun1(); // 正确,只能调用对象的 public 办法
47     //s.Son_fun2(); // 谬误:不能调用对象的 protected 办法
48     //s.Father_show1();
49     //s.Father_show2();
50     //s.Son_fun3(); // 谬误:不能调用对象的 private 办法
51     //s.Father_show3();
52     return 0;
53 }

对爱护继承的了解:

1. 三种属性能力的强弱:public<protected<private

2. 爱护继承相当于先将从父类继承的所用成员都放在子类的 protected 局部:

 1 class Son:public Father{
 2 /*
 3 protected:
 4     public:
 5         void Father_show1(){
 6             cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
 7         }
 8     protected:
 9         void Father_show2(){
10             cout<<"调用 Father 类的 protected 办法:Father_show2"<<endl;
11         }
12     private:
13         void Father_show1(){
14             cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
15         }    
16 */ 
17 public:
18     Son()=default;
19     void Son_fun1(){
20         cout<<"调用 Son 类的 public 办法:Son_fun1"<<endl;
21         Father_show1();
22         Father_show2();
23         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
24     }
25 protected:
26     void Son_fun2(){
27         cout<<"调用 Son 类的 protected 办法:Son_fun2"<<endl;
28         Father_show1();
29         Father_show2();
30         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
31     }
32 private:
33     void Son_fun3(){
34         cout<<"调用 Son 类的 private 办法:Son_fun3"<<endl;
35         Father_show1();
36         Father_show2();
37         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
38     }
39 };

而后和私有继承一样,依据三种属性能力的强弱决定成员的属性在子类中到底是 public、protected 还是 private:

• 因为 public<protected, 因而办法 Father_show1()在类 Son 中是 protected 办法

• 因为 protected=protected,因而办法 Father_show2()在类 Son 中是 protected 办法

• 就像在私有继承中剖析的那样,Father_show3()在类 Son 中尽管是 private 办法,但 Son 类中的任何成员办法都不能在其函数体中调用办法 Father_show3()

3. 对象只能调用 public 局部的成员,此时办法 Father_show1()是对象的 protected 办法,因而无奈像私有继承那样再被显式调用了

• 公有继承

将下面的示例改为公有继承:

 1 #include<iostream>
 2 using namespace std;
 3 class Father{
 4 public:
 5     Father()=default;
 6     void Father_show1(){
 7         cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
 8     }
 9 protected:
10     void Father_show2(){
11         cout<<"调用 Father 类的 protected 办法:Father_show2"<<endl;
12     }
13 private:
14     void Father_show3(){
15         cout<<"调用 Father 类的 private 办法:Father_show3"<<endl;
16     }
17 }; 
18 
19 class Son:private Father{
20 public:
21     Son()=default;
22     void Son_fun1(){
23         cout<<"调用 Son 类的 public 办法:Son_fun1"<<endl;
24         Father_show1();
25         Father_show2();
26         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
27     }
28 protected:
29     void Son_fun2(){
30         cout<<"调用 Son 类的 protected 办法:Son_fun2"<<endl;
31         Father_show1();
32         Father_show2();
33         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
34     }
35 private:
36     void Son_fun3(){
37         cout<<"调用 Son 类的 private 办法:Son_fun3"<<endl;
38         Father_show1();
39         Father_show2();
40         //Father_show3(); // 谬误:无奈调用 Father 类的 private 办法 
41     }
42 };
43 
44 int main(){
45     Son s;
46     s.Son_fun1(); // 正确,只能调用对象的 public 办法
47     //s.Son_fun2(); // 谬误:不能调用对象的 protected 办法
48     //s.Son_fun3(); // 谬误:不能调用对象的 private 办法
49     //s.Father_show1();
50     //s.Father_show2();
51     //s.Father_show3();
52     return 0;
53 }

对公有继承的了解:

1. 三种属性能力的强弱:public<protected<private

2. 公有继承相当于先将从父类继承的所用成员都放在子类的 private 局部:


 1 class Son:public Father{
 2 /*
 3 private:
 4     public:
 5         void Father_show1(){
 6             cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
 7         }
 8     protected:
 9         void Father_show2(){
10             cout<<"调用 Father 类的 protected 办法:Father_show2"<<endl;
11         }
12     private:
13         void Father_show1(){
14             cout<<"调用 Father 类的 public 办法:Father_show1"<<endl;
15         }    
16 */ 
17 public:
18     Son()=default;
19     void Son_fun1(){
20         cout<<"调用 Son 类的 public 办法:Son_fun1"<<endl;
21         Father_show1();
22         Father_show2();
23         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
24     }
25 protected:
26     void Son_fun2(){
27         cout<<"调用 Son 类的 protected 办法:Son_fun2"<<endl;
28         Father_show1();
29         Father_show2();
30         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
31     }
32 private:
33     void Son_fun3(){
34         cout<<"调用 Son 类的 private 办法:Son_fun3"<<endl;
35         Father_show1();
36         Father_show2();
37         //Father_show3();// 谬误:无奈调用 Father 类的 private 办法 
38     }
39 };

而后和私有继承一样,依据三种属性能力的强弱决定成员的属性在子类中到底是 public、protected 还是 private:

• 因为 public<private, 因而办法 Father_show1()在类 Son 中是 private 办法,但类 Son 中的成员办法能够在函数体内调用该办法

• 因为 private>protected,因而办法 Father_show2()在类 Son 中是 prijvate 办法, 但类 Son 中的成员办法能够在函数体内调用该办法

• 就像在私有继承中剖析的那样,Father_show3()在类 Son 中尽管是 private 办法,但 Son 类中的任何成员办法都不能在其函数体中调用办法 Father_show3()

3. 对象只能调用 public 局部的成员,此时办法 Father_show1()是对象的 private 办法,因而无奈像私有继承那样再被显式调用了

QUESTION:爱护继承(protected)和公有继承(private)有何不同?

ANSWER:在下面的例子中,咱们发现爱护继承形式和公有继承形式达到的成果齐全一样,难道这两中继承形式没有任何区别吗?咱们先来看一个例子:

 1 #include<iostream>
 2 using namespace std;
 3 class GrandFather{ // 祖父类 
 4 public:
 5     GrandFather()=default;
 6     void GrandFather_show(){
 7         cout<<"调用 GrandFather 类的办法:GrandFather_show"<<endl; 
 8     }
 9 };
10 class Father:protected GrandFather{ // 父类 
11 public:
12     Father()=default;
13 };
14 class Son:public Father{ // 子类
15 public:
16     Son()=default;
17     void Son_show(){
18         cout<<"调用 Son 类的办法:Son_show"<<endl;
19         GrandFather_show(); 
20     }
21 }; 
22 
23 int main(){
24     Son s;
25     s.Son_show();
26     return 0;
27 }

咱们发现下面的程序能够顺利运行。这是因为当 Father 类以保护方式(protected)继承 GrandFather 类时,GrandFather 类中的私有办法 GrandFather_show()会以 protected 办法的模式存在于类 Father 中,当类 Son 再以私有形式(public)继承类 Father 时,办法 GrandFather_show()会仍以 protected 办法的模式存在与类 Son 中,因为一个类中的成员办法容许在其函数体内调用 protected 局部的成员,因而零碎容许在 Son 类的成员办法 Son_show()调用办法 GrandFather_show(),从而使程序顺利运行。

当初咱们将程序改为 Father 类以公有继承的形式继承 GrandFather 类:

 1 #include<iostream>
 2 using namespace std;
 3 class GrandFather{ // 祖父类 
 4 public:
 5     GrandFather()=default;
 6     void GrandFather_show(){
 7         cout<<"调用 GrandFather 类的办法:GrandFather_show"<<endl; 
 8     }
 9 };
10 class Father:private GrandFather{ // 父类 
11 public:
12     Father()=default;
13 };
14 class Son:public Father{ // 子类
15 public:
16     Son()=default;
17     void Son_show(){
18         cout<<"调用 Son 类的办法:Son_show"<<endl;
19         GrandFather_show(); 
20     }
21 }; 
22 
23 int main(){
24     Son s;
25     s.Son_show();
26     return 0;
27 }

咱们发现程序报错。这是因为当 Father 类以公有(private)继承 GrandFather 类时,GrandFather 类中的私有办法 GrandFather_show()会以 private 办法的模式存在于类 Father 中,换句话说办法 GrandFather_show()变成了类 Father 的“隐衷”;当类 Son 再以私有形式(public)继承类 Father 时,因为“儿子无奈利用父亲的“隐衷”进行交易”,因而无奈在 Son 类中的任何成员办法中调用 GrandFather_show()办法,包含 Son_show()。此时如果咱们将类 Son 中成员函数 Son_show()中的语句“GrandFather();” 正文掉,程序便能够从新顺利执行。

 1 #include<iostream>
 2 using namespace std;
 3 class GrandFather{ // 祖父类 
 4 public:
 5     GrandFather()=default;
 6     void GrandFather_show(){
 7         cout<<"调用 GrandFather 类的办法:GrandFather_show"<<endl; 
 8     }
 9 };
10 class Father:private GrandFather{ // 父类 
11 public:
12     Father()=default;
13 };
14 class Son:public Father{
15 public:
16     Son()=default;
17     void Son_show(){
18         cout<<"调用 Son 类的办法:Son_show"<<endl;
19         //GrandFather_show(); 
20     }
21 }; 
22 
23 int main(){
24     Son s;
25     s.Son_show();
26     return 0;
27 }


#** 友元 **

正文完
 0