C++_类和对象(1)

先来回顾一下结构体:

结构体是一些数据的集合,这些数据可以是不同类型,在C语言中结构体中不能定义函数,在C++中结构体可以定义函数。

结构体中有内存对齐问题,可以参考以前的文章:点击打开链接

但在C++中,结构体中有函数的定义更喜欢用类(class)来表示。

一、类的定义

两种方式:1)类的声明和定义全在类体中

                2)类的声明在.h文件中,类的定义在.cpp文件中。

//声明和定义都在类体中
class A  //A为类名
{
	//类体:由函数和变量组成
public:
	void FunTest()  //类的方法/类的成员函数
	{
		cout << "This is FunTest" << endl;
	}
private:
	int a; //类的成员变量
};

int main()
{
	A a;
	a.FunTest();
	return 0;
}

第二种:

//.h
class B
{
public:
	void test();
private:
	int _b;
};
//.cpp
#include "test.h"

void B::test()  //此处要写返回值 
{
	cout << "This is Test!" << endl;
}

int main()
{
	B b;
	b.test();
	return 0;
}

二、封装

说到类,就要说一下C++第一个特性:封装

    1)封装:隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互,将数据和操作数据的方法进行有机结合。

函数也是封装的一种形式,函数中的语句被封装在函数本身这个更大的实体中,被封装的实体隐藏了其实现细节,可以调用该函数但不能访问函数中的语句。

    2)封装一般通过访问限定符实现:public(公有)、protected(保护)、private(私有)

        说明:1.public成员可以在类外进行访问,protectrd和private在类外不能进行访问

                  2、作用域从该访问限定符出现的位置直到下一个访问限定符出现

                  3.class的默认访问权限是private,而struct为public

三、类的作用域

    类定义了一种新的作用域--类域,类中的所有成员都必须在类域中。形参表和函数体处于类的作用域中。在类外定义成员,需要使用::作用域解析符指明成员处于哪一个类域中。在类的作用域外,只能通过对象或指针借助成员访问操作符->来访问类成员,跟在访问操作符后面的名字必须在类的作用域中。

    成员变量在类中具有全局作用域。

int a = 20;
class Test
{
public:
	void Seta(int a)   //两个a均来自形参,就近原则
	{
		a = a;
	}
	void PrintA()
	{
		cout << "a=" << a << endl;
	}
private:
	int a = 10;
};

int main(void)
{
	int a = 40;
	Test t;
	t.Seta(1);
	t.PrintA();   //10
	cout << a << endl;  //40  先在函数作用域中找,找不到再去全局变量中找
	Test *p = new Test;  //通过指针访问类成员
	p->PrintA(); //10
	delete p;
	return 0;
}

四、类的实例化

1.实例化

    1)定义:用类类型创建对象的过程,称为类的实例化。

    2)说明:    1>类只是一个模型一样的东西,限定了类中有哪些成员,定义出一个类并没有分配实际的内存空间来存储。

                    2>一个类可以实例化多个对象,实例化出的对象占用实际的物理空间来存储类中的成员变量

2、类的对象模型

看一段简单的代码:

class Test
{
public:
	void FunTest()
	{
		cout <<_a << endl;
	}
private:
	int _a;
};

int main()
{
cout << sizeof(Test) << endl;  //4
	return 0;
}

其中类的大小为4,看一下内存

  

可以看出类的大小就是成员变量所占内存,类中的成员函数并没有占用内存。

class Test
{
public:
	void FunTest()
	{
		cout <<_a << endl;
	}
private:
	char _a[20];
	char _b[3];
	int _c;
};

int main()
{
	Test t;
	cout << sizeof(t) << endl;  //28
	return 0;
}

从以上代码可以看出,类中存储方式也是遵循内存对齐的,和结构体一样。

class Empty
{
};
int main()
{
	cout << sizeof(Empty) << endl;  //1
	return 0;
}

注意:空类的大小为1,不是0,

            因为类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。所有,空类也会实例化,编译器给空类添加了隐含的一个字节,这样空类实例化后也会有自己的一个地址

内存对齐的好处:便于处理器进行内存访问,提高效率

五、this指针

我们发现在调用类的成员函数时,不需要传类的成员变量,也能对类的成员变量进行操作,可能是因为在类中有一个默认字节保存了一个指向成员变量的指针,但在求大小的时候,类的成员函数并没有占内存,排除了这种可能。另一种可能是类的成员变量是全局变量,但在使用之前并没有看见其声明,定义在使用之后,不符合全局变量的规则。但我们在看程序的反汇编时,发现了一个新的东西-->this指针。


C++类中成员函数有一个隐藏的指针,指向了调用该函数的对象本身。

    this指针的特性:

        1>类型:类类型 * const

        2>this指针并不是对象本身的一部分,不影响sizeof的结果

        3>this的作用域在类非静态成员函数的内部

        4>this指针是类成员函数的第一个默认隐含参数,编译器自动维护传递。

        5>只有在类的非静态成员函数中才可以使用this指针,其他函数都不可以。

    _thiscall调用约定:是一种调用方式

        1>_thiscall只能用在类的成员函数上

        2>参数从右向左压栈

        3>如果参数个数确定,this指针通过ecx传递给被调用者;如果参数不确定,this指针在所有参数被压栈后压入堆栈

        4>参数个数不确定,调用者自主清理,否则函数自己清理。



猜你喜欢

转载自blog.csdn.net/warrior_harlan/article/details/80611004