类和类型

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

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

内存对齐

内存对齐基本上是透明的,这是编译器该干的活,编译器为程序中的每个数据单元安排在合适的位置上,从而导致了相同的变量,不同声明顺序的结构体大小的不同。
减少不必要的内存开销, 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:
      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;}
12     private:
13         void Father_show1(){
14             cout<<"调用Father类的public方法:Father_show1"<<endl;
15         }     
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:

• 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 }
c++里面的struct和class区别

默认继承权限不同,class继承默认是private继承,而struct默认是public继承
class还可用于定义模板参数,像typename,但是关键字struct不能同于定义模板参数

友元

使用场景:和封装关联,不可能通过关键字适用所有的权限问题,C++通过友元机制允许类的非公有成员被其他的类或者非成员函数访问

//普通函数友元
class Point{friend double GetDistance((Point p1);};
double getDistance ((Point p1){...}
//类成员函数友元
class Point{
 friend double Line::getDistance(Point p1);};
};
class Line{
 double getDisantancd(Point p1);
};
// 类友元
class Point{
  friend class Line;
};
class Line{
 double getDistance(Point p1);
};

友元特性

  1. 友元只有单向性: 若B是A的友元, A不一定是B的友元,要看类中是否具有相应的声明
  2. 友元不能被继承:B是A的友元,C是B的子类, 推不出C是A 的友元
  3. 友元不具备传递性
  4. 在类里面一起声明和定义友元,(友元类或者友元函数都可以)默认是extern, 在外部都是可以访问的
    类成员函数会存在嵌套的问题:定义和声明拆开加前向申明

Connie
4 声望0 粉丝

« 上一篇
从c到c++