C++中类(class)和结构(struct)的区别
类描述看上去很像包含成员函数以及public和private可见性标签的结构声明,实际上,C++对结构进⾏了扩展,使之具有与类相同的特性。它们之间的唯⼀区别是:结构的默认访问类型是public,⽽类的默认访问类型为private。在C++中通常使⽤类来实现类描述,⽽把结构限制为只表⽰纯粹的数据对象(常被称为普通⽼数据POD(Plain Old Data)结构,)。
C和C++中结构体的不同:
C语⾔中的结构体不能为空,否则会报错
C语⾔中的结构体只涉及到数据结构,⽽不涉及到算法,也就是说在C中数据结构和算法是分离的。换句话说就是C语⾔中的结构体只能定义成员变量,但是不能定义成员函数。
在C++中既可以定义成员变量⼜可以定义成员函数, C++中的结构体和类体现了数据结构和算法的结合。
虽然C语⾔的结构体中不能定义成员函数,但是却可以定义函数指针,不过函数指针本质上不是函数⽽是指针,所以总的来说C语⾔中的结构体只是⼀个复杂数据类型 ,只能定义成员变量,不能定义成员函数,不能⽤于⾯向对象编程。
在 C 中,必须显式使⽤ struct 关键字来声明结构。 在 c + + 中,不需要在 struct 定义类型后使⽤关键字。
C++中类和结构
结构是实值类型(Value Types),⽽类则是引⽤类型(Reference Types)。
结构使⽤栈存储(Stack Allocation),⽽类使⽤堆存储(Heap Allocation)。
概念:class和struct的语法基本相同,从声明到使⽤,都很相似,但是struct的约束要⽐class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不⼀定做的到。
类型:struct是值类型,class是引⽤类型,因此它们具有所有值类型和引⽤类型之间的差异。
效率:由于栈的执⾏效率要⽐堆的执⾏效率⾼,但是栈资源却很有限,不适合处理逻辑复杂的⼤对象,因此struct常⽤来处理作为基类型对待的⼩对象,⽽class来处理某个商业逻辑。
总结:
(1) 在表⽰诸如点、矩形等主要⽤来存储数据的轻量级对象时,⾸选struct。
(2) 在表⽰数据量⼤、逻辑复杂的⼤对象时,⾸选class。
(3) 在表现抽象和多级别的对象层次时,class是最佳选择
如果⽤C语⾔实现⼀个类似⾯向对象的类
typedef struct Actress {
int height;// ⾝⾼
int weight;// 体重
int age;// 年龄(注意,这不是数据库,不必⼀定存储⽣⽇)
void(*desc)(struct Actress*);
} Actress;
void profile(Actress* obj){
printf("height:%d weight:%d age:%d\n", obj->height, obj->weight, obj->age);
}
int main(){
Actress a;
a.height =168;
a.weight =50;
a.age =20;
a.desc = profile;
a.desc(&a);
return0;
}
想达到⾯向对象中数据和操作封装到⼀起的效果,只能给struct⾥⾯添加函数指针,然后给函数指针赋
值。在C语⾔的项⽬中你很少会看到这种写法,主要原因就是函数指针是有空间成本的。⼀般会按照如下的⽅法写:
// 写法⼆
#include<stdio.h>
typedef struct Actress {
int height;// ⾝⾼
int weight;// 体重
int age;// 年龄(注意,这不是数据库,不必⼀定存储⽣⽇)
} Actress;
void desc(Actress* obj){
printf("height:%d weight:%d age:%d\n", obj->height, obj->weight, obj->age);
}
int main(){
Actress a;
a.height =168;
a.weight =50;
a.age =20;
desc(&a);
return0;
}:
再看⼀个普通的C++类:
class Actress {
public:
int height;// ⾝⾼
int weight;// 体重
int age;// 年龄(注意,这不是数据库,不必⼀定存储⽣⽇)
void desc(){
printf("height:%d weight:%d age:%d\n", height, weight, age);
}
};
int main(){
Actress a;c语言中struct
a.height =168;
a.weight =50;
a.age =20;
a.desc();
return0;
}
看着像写法⼀?其实相当于写法⼆。C++编译器实际会帮你⽣成⼀个类似C语⾔写法⼆的形式(这也算是C++ zero overhead指导⽅针的⼀个体现)。看到这⾥就明⽩了:C++中类和操作的封装只是对于程序员⽽⾔的。⽽编译器编译之后其实还是⾯向过程的代码。编译器帮你给成员函数增加⼀个额外的类指针参数,运⾏期间传⼊对象实际的指针。类的数据(成员变量)和操作(成员函数)其实还是分离的。
每个函数都有地址(指针),不管是全局函数还是成员函数在编译之后⼏乎类似。
C++结构体和类总结
结构体和类最⼤的区别就是前者访问控制默认为public,⽽类的默认访问控制是private。⽽对于public,private,protected的访问控制都是在编译期间由编译器检查的,编译通过后,程序执⾏过程中就不存在什么访问限制了。笼统⼀点讲,它们在底层只是类型名称不同,原理都相同。
类与对象,类是⼀个抽象的概念,⽽对象则是这个抽象概念⾥的⼀个具体实例。(如⼈–CXX…)类⼀般由数据成员和函数成员组成,⽽具体对象⼤⼩的计算只看数据成员,函数成员属于执⾏代码,不属于类对象的数据。除本⾝外,类中的数据成员可以是任何已知的数据类型。
为什么类中不能定义⾃⾝的对象呢?因为类在实例化时,必须要知道它的⼤⼩,⽽如果有⾃⾝,会形成递归定义,没有出⼝。但注意⾃⾝的指针类型是可以的,因为任何类型的指针⼤⼩是已知的。
类对象⼤⼩⼀般就是数据成员⼤⼩之和,但也有些特殊情况不符合这个公式。(1)空类,⾄少占1字节⼤⼩,⽽不是不占内存空间,如果不占内存⼤⼩,那么空类就⽆法实例化。但是空类就算没有数据成员,也可以有函数成员的,所以仍然需要实例化,⽽这个⾄少会分配1字节空间给空类,就是⽤于实例化的。(2)字节对齐 (3)静态成员数据,类似局部静态数据,存在域全局,作⽤域局部,在编译期间就已经初始化,保存在全局数据区中。它的⼤⼩不算在类对象⾥。
this指针:使⽤过程中被编译器给隐藏起来了,它其实就是个指针,保存调⽤对象的⾸地址,指向当前调⽤者对象本⾝。对象的成员函数形参处隐式的有这个this,其实是在调⽤成员函数时,编译器做了⼀个⼩动作:利⽤寄存器ecx保存了对象的⾸地址(this),并以寄存器传参的⽅式传递到成员函数中。这也是在成员函数中能直接访问成员数据的原因(this->data),也是判断⼀个函数不是⼀般函数⽽是成员函数的依据。
对象作为函数参数:这个不像数组做参数只传递⾸地址,⽽是将对象的所有数据成员拷贝⼀份全部传递过去。这个过程其实会调⽤系统的拷贝构造函数,就是简单的赋值过程(如果⾃⼰写了这个函数,会替换系统的),所以对于有动态内存分配的类,使⽤这种传参,调⽤系统的拷贝构造函数,会出现⼀个这样的错误,这种传参其实是实参与形参处的两个对象保存着相同的数据,⽽形参处对象在函数调⽤结束就会释放调⽤对应的析构函数,所以对于实参和参数处的两个对象都指向的动态空间被释放了。这时实参处对象的指针还在,但所指内存已经释放了。所以对于这种需要我们⾃⼰定义拷贝构造函数,⼀般有两种思路:(1)深拷贝数据,即对于指针数据不仅拷贝指针本⾝⽽且指针所指数据也同时拷贝(2)设置引⽤计数。但是对于对象传参我们⼀般使⽤指针或引⽤形式,这样即可以避免上⾯所说错误,同时效率也更⾼。
对象作为返回值:情况和对象作为函数参数⼀样。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。