struct和class之间问题(+引发的个人思考,和对共用体思考)

一、C语言中的struct

在C语言中,struct是一种自定义数据类型,所以在C语言中,struct不能包含任何函数,否则编译器会报错。因为C语言是面向过程的编程。采用过程性编程首先考虑要遵循的步骤,然后考虑如何表示这些数据。也就是先考虑过程后考虑数据,这样方法和数据就分开了。而在C语言中结构体就是为了考虑数据的封装而存在的。
还有就是在C语言中不能存在空结构体,否则编译器会报错。原因很简单,C语言中结构体就是为了封装数据类型,统一为一个新的struct数据类型,既然是封装数据而存在,那么定义一个结构体不给任何数据,那还封装个什么。
所以总结就是:
(1)C语言中的结构体只是封装数据用的,不能包含任何函数。
(2)C语言中的结构体不能为空结构体。

二、C++中的struct

首先C++是面向对象的编程。首先考虑数据,同时还要考虑如何使用数据。对待一种事物,首先用一个对象表示这个事物 的方方面面,包括对象的属性,和对对象的属性(数据)的操作。即首先从用户的角度考虑对象,描述对象所需要的数据,以及描述用户与数据交互所需要的操作。完成对接口的描述后,需要确定如何实现接口和数据的存储,最后使用新的设计方案创建出程序。这里可以说就是面向对象的原则之一:“依赖倒转原则”。依赖接口编程序。
在C++中struct与class没有什么特别的区别。唯有畅谈的一个区别,就是struct里的数据成员默认都是public类型的,而class里面的数据类型默认是private类型的。为什么会这样呢?主要还是为了兼容C语言程序中的结构体,C语言程序中的结构体就是随便访问数据的。C++里在兼容C语言程序中的struct的同时,尽量将struct和class的其他属性设置成一致。所以C++中的struct除了默认属性是public之外,其他和class的使用没有区别,包括构造函数,析构函数,可以有空类,也允许有空结构体。
所以总结就是:
(1)C++中的结构体默认属性是public属性。
(2)C++中的结构体出去第一点之外,其他的使用和class一样。包括有默认构造函数,默认析构函数,可以自定义构造函数,可以有其他成员函数,也可以像class一样为一个空体。

另外在C语言里结构体内的变量不可以初始化,因为在用结构体定义变量之前,没有给struct分配栈空间(在网上搜了好多,都是这样说的),换句话说C语言里struct只是一个自定义变量类型,怎么可能直接给变量类型里面的东西赋值呢?比如int也是一个变量类型,怎么可能把int里面的东西赋值呢,所以struct也是这个意思。只有用struct定义出来变量的时候,给定义出来的变量赋值。
注意,这个时候就更不能将C++的结构体和C语言的结构体相提并论,因为C语言结构体只是一个单纯的自定义数据类型,但是在这里struct已经超脱普通自定义类型概念了,因为这里struct里面可以用成员函数,是封装数据和方法的类型,是一个包含代码实现设计的封装。
但是C++的结构体和类却可以初始化,按道理说,类和结构体我们都说没有实例化,没有分配栈空间。创建对象才是实例化,分配栈空间,构建对象,这个时候才有真正意义。这样想的话,感觉C++里面的类和结构体也不可以给成员变量初始化。但是事实是可以初始化的。
如下变量初始化代码及运行情况:

class A
{
public:
	int m_val = 10;
	int m_tmp = 20;
};

struct B
{
	int s_a = 90;
	int s_b = 100;
};

int main()
{
	A a;
	A b;
	cout << a.m_val<< endl;
	cout << b.m_tmp <<endl;

	B c;
	B d;
	cout << c.s_a << endl;
	cout << d.s_b << endl;
	
	return 0;
}

在这里插入图片描述
如果我们不初始化直接输出呢?我没有敲代码看结果之前,我觉得要么就是随机值,要么就是0。我在博客上还搜了一下,发现有一篇**2015年博客**说在C++里结构体里面变量不初始化的话,创建对象输出变量值是0,类创建对象,输出成员变量值是随机值。于是我敲了几行代码自己看一下结果,发现并非如此。代码及输出结果如下:

class A
{
public:
	int m_val;
	int m_tmp;
};

struct B
{
	int s_a;
	int s_b;
};

int main()
{
	A a;
	A b;
	cout << a.m_val<< endl;
	cout << b.m_tmp <<endl;

	B c;
	B d;
	cout << c.s_a << endl;
	cout << d.s_b << endl;
	
	return 0;
}

运行结果:
在这里插入图片描述
直接报错!既不是0也不是随机值。更不是结构体里面变量是0,类里面成员变量是随机值。这个基本可以确定是跟编译器有关。因为我看的那篇博客里面有代码和运行结果,而且是2015年博客,编译器肯定更加完善,发现有明显不合适的使用时,直接报错。
我觉得这些问题可以自己思考动手实践看结果。可以引发兴趣,在网上查资料思考。但是一直纠结深究觉得没必要,一般情况下,在C++里我们只把类(struct)看成对数据和方法封装的东西。里面包括一些设计和实现。创建对象的时候,类才算配的上用场,所以即使现在编译器允许初始化,我们也一般情况下不初始化。创建对象的时候,再对对象的数据成员进行初始化赋值等操作。(如果类里面有常变量或者其他必须定义的时候就初始化的变量,我们才给一个初始值)。

三、C++中空结构体和类大小

直接用程序计算看一下:

struct A
{

};

class B
{

};
int main()
{
	A a;
	cout << sizeof(a) << endl;

	B b;
	cout << sizeof(b) << endl;

	return 0;
}

运行结果:
在这里插入图片描述
空类和空对象的大小都是1(由于这里结构体和类一样,就单独讨论类)。
这是因为C++中标准规定,任何不同的对象不能拥有相同的内存地址。如果空类大小为0,文声明这个类的对象数组,那么数组中每个对象内存都是0,导致数组中的它们都拥有了相同的地址,这样违背了C++标准。
所以,不只是类,其他任何类型,都不允许大小为0。所以编译器为每个空类空结构体都增加了一个虚设的字节(书上得知有的编译器可能不止增加一个虚设字节)。这样就可以保证空对象和空结构体的大小不会是0,保证了它们的对象拥有彼此独立的空间。
还有之前听到老师说的另一种解释说是因为空类里面有默认构造函数和析构函数,所以大小为1字节,但是我理解不了,查完资料之后我更相信上面C++标准规定的说法,对老师的这一个观点存质疑态度。

在这里提出对象必须拥有彼此独立的空间,就想到了共用体。共用体是一种数据格式,能够存储不同的数据类型,但只能同时存储其中一种数据类型。就想着共用体里有两个对象会怎么样,这个时候是两个对象用同一个空间?这样就违背了前面说的编译器要求对象必须有独立的空间,用共用体定义一个变量的时候,里面的对象会调用构造函数吗?如果都调用构造函数的话,那就是两个对象用一个空间了,如果为了避免两个对象用一个空间而只选择一个对象构造的话,那么会选择哪一个对象构造呢?
突然想起很多,打开VS敲了一下代码,一开始想要看一下共用体里面的两个对象的构造和析构情况,我们使用共用体里面的对象的时候至少同时存在一个对象,所以至少会有一个对象调用构造函数,那么如果先构造的对象还没析构就构造了另一个对象的话,那么就产生了两个对象同时存在一个空间,就违背了上面的理论。所以理想情况下,应该是一个对象使用这个空间,另一个对象使用前,前一个对象一定会调用析构函数销毁,另一个对象才会调用构造函数,这样就完美岔开了,就不会说两个对象同时存在一个空间中。为了清楚的看到构造析构的过程和顺序写出如下代码:

class A
{
	A() 
	{
		cout << "一个对象构造" << endl;
	}
	~A() 
	{
		cout << "一个对象销毁" << endl;
	}
public:
	int m_val;
};
int main()
{
	union UU
	{
		A a;
		A b;
	};
	UU t;

	return 0;
}

写到UU t;这句代码的时候就报错了,说“无法引用共用体的默认构造函数——它是已删除的函数”。看起来是因为构造函数被我们重写造成的。但是当我把构造函数删除,只留下一个析构函数的时候,还是会报这样的错误。当把构造函数和析构函数都删除才没有报错。如下代码:

class A
{
public:
	int m_val;
};
int main()
{
	union UU
	{
		A a;
		A b;
	};
	UU t;
	t.a.m_val = 10;
	t.b.m_val = 20;
	cout << t.a.m_val << endl;
	cout << t.b.m_val << endl;

	return 0;
}

运行结果:
在这里插入图片描述
因为我们不能写构造函数和析构函数,所以最后也没得出什么结果。但是由于共用体要求里面的数据类型要求某一时刻只能有一个成员是当前成员。所以应该是a和b是不同时存在的,用共用体切换使用它们俩的时候,应该一直不断的伴随着对象的构造和析构,只不过我们没办法重写构造函数和析构函数在里面添加输出语句来观察构造和析构过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟小胖_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值