C++类和对象(一)

类定义

  1. class是关键字,stack是类名,类名就是类型,用stack定义一个变量stack x;类里面的变量是成员变量,函数称为成员函数
class stack
{
   //函数体
};
int main()
{
   stack x;
}
  1. 为了区分成员变量,一般习惯上成员变量加一个特殊标识,如_或者m开头,防止成员变量和参数同名
    例如:year, m_year,year,mYear
  2. struct也可以定义一个类
  3. 在类中成员变量可以随意定义在哪,只要是在类中,但一般习惯函数在上,成员变量在下
  4. 在类里面定义是内联函数,在类里面声明,在类外定义不是内联函数
class Date
{
public:
    //函数声明,不是内联函数
    void print();
    void Print()
    {
    // inline void Printf()
    //内联函数
       cout << "Data::Printf" << endl;
    }
    int year;
    int month;
    int day;
};

void Date::print();
{
   //不是内联函数
   cout << "Data::printf" << endl;
}
  1. C++兼容C的struct的用法,C++可以使用struct用法,也可以用类的用法

访问限定符

1.public:公共的,在类外用 . -> :: 可以直接访问
private:私有的,在类外不能直接访问
protected:被保护的,在类外也不能直接访问
private和protected体现了封装的特性,就是不能让类外随意访问,是被保护的

2.class类中没有被访问限定符修饰被认为是private,struct类中的是public

3.访问限定符的作用域是从访问限定符出现到下一个访问限定符为止,如果后面没有访问限定符,就到 } 结束

类域

1.在域外定义一个成员函数要用 :: 域作用限定符,指明它是哪个类域的。
2.要指定类域去查找,不然函数会在全局域中找,找不到就会报错,类域影响的是编译时的查找。

class Date
{
public:
	void print();
	void Print()
	{
		cout << "Data::Printf" << endl;
	}
	void init(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

//到指定的类域中去查找
void Date::print()
{
	cout << "Data::printf" << endl;
}

实例化

1.实例化的定义是:用类类型在物理内存上创建对象的过程,称为实例化对象
2.类是没有空间的,只是声明,类实例化出对象才会开空间
3.类和对象的关系:一对多的关系,一个类可以实例化出多个对象,类就像是设计图,对象就像是房子,一个设计图可以创建多个空间相同的房子,房子里可以放数据不同参数类型相同的成员变量和数据不同参数类型相同成员函数

Date::_day = 2;//这会报错
//类只是图纸,没有空间,只声明,没有空间
//定义要开空间,比如一个函数定义了才有空间

//实例化出x这个对象开了空间
x._day = 2;//可以使用

类中成员变量是私有的不能直接在类外用 :: 访问
但是公有的可以在类外用 :: 访问

void Date::Init(int year,int month,int day)
//这样可以访问类这个域中的成员函数,可以访问公有的、
//也可以访问私有的
class Date
{
private:
	void init(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	int _year;
	int _month;
	int _day;
};

void Date::print()
{
	cout << "Data::printf" << endl;
}

对象的大小

Date x1,x2,用Date创建两个对象,两个对象中都有各自独立的_year,day,_month存储不同的数据,但是调用相同的函数Print,如果类里面存储100个Print函数的指针,那么会浪费大量的空间,所以类中不存储函数指针

对象中只存成员变量,C++规定实例化对象也要符合内存对齐规则

对齐规则和C语言结构体的对齐规则是一样的这里就不多说了,这里重点说一下,没有成员变量的类是空类,内存大小是1,就是为了表示对象存在,仿函数是没有成员变量的类

为什么内存对齐?
内存对齐不是浪费空间吗?
因为内存对齐和硬件有关,具体来说是CPU不能从任意位置开始读和数据总线有关,比如CPU规定从整数倍开始读,读整数倍

this指针

1.概念:不同的对象用相同的函数,结果不同,this指针可以解决这个问题,this可隐式地传地址,从而得到的结果不同
2.编译器编译后,类的成员函数都会在形参的第一个位置,自动生成一个当前类类型的this指针,比如Date类
void Init(Date* const this,int year,int month,int day);

Date* const this
this 本身不能被修改,this(x)
this的指向可以被修改

3.this不能在函数的形参和实参显示写出来,但是能够在函数体内显示地写this,平常也不在函数体内写,因为编译器会自动补充

4.类的成员函数中访问成员对象,本质上是通过this->_year = year


class Date
{
	//void Init(Date* const this,int year,int month,int day);
public:
	void Init(int year, int month, int day)
	{
		//this->_year = year;
		_year = year;
		_month = month;
		_day = day;
	}
private:
    //只是声明
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date x;
	//x.Init(&x,2024,7,12);
	x.Init(2024, 7, 12);
	
	return 0;
}

下面有三个问题:

  • this指针是存在哪里的?

形参this默认存在
VS中如果this频繁使用,会放在寄存器

  • 下面程序的运行结果是:C
    A.编译报错:语法错误
    B.运行崩溃:空指针
    C.正常运行
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "A::Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
//不是解引用,在汇编下是把p的地址给寄存器ecx,然后call跳转到print()的地址,也可以这样说,类内部是没有存储指针的,p这个对象在类内是找不到指针的,自然这不可能是解引用,而是在编译就做好的函数跳转指令
p->_a = 1;
//空指针解引用,_a存在对象当中,函数地址并不在对象当中

return 0;
}
  • 下面程序的运行结果是:B
    A.编译报错:语法错误
    B.运行崩溃:空指针
    C.正常运行
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "A::Print()" << endl;
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
//传递p的地址给ecx,p的地址传参给this,this->_a对类体内变量的解引用会崩溃,_a存在于类体内,可以找到
//this是隐式地传参
return 0;
}

访问限定符只限定对类外的访问,不限制对类内的访问

C++和C语言Stack的对比

C++比C更加方便

类 == 类名
C语言中,Stack中需要typedef结构体类型,C++中可以直接用类名作为类型,C还需要显示地传结构体的指针,C++隐含的this指针帮我们传了对象的指针,C++的Init函数的缺省参数方便很多,不传参时是用默认的缺省值4,如果知道要开的空间大小,传实参时可以直接传这个大小

最大的魅力还是C++具有封装的特性,C++把变量和函数都放进一个类域中,想要给类外访问的设置为public,不给类外访问的设置为private,所以C++的成员函数和变量不能随意改变,具有封装的特性,避免了胡乱的修改,而C变量和函数各自独立,可以随意访问,不太严谨,具有风险。

相关推荐

  1. C++ --> 对象

    2024-07-14 09:38:03       22 阅读
  2. C++对象

    2024-07-14 09:38:03       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 09:38:03       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 09:38:03       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 09:38:03       62 阅读
  4. Python语言-面向对象

    2024-07-14 09:38:03       72 阅读

热门阅读

  1. 【AI原理解析】—对抗学习(AL)原理

    2024-07-14 09:38:03       28 阅读
  2. 【nginx】nginx的优点

    2024-07-14 09:38:03       24 阅读
  3. C++多态

    C++多态

    2024-07-14 09:38:03      28 阅读
  4. B树:深入解析与实战应用

    2024-07-14 09:38:03       25 阅读
  5. C语言调用python

    2024-07-14 09:38:03       25 阅读
  6. pytorch GPU cuda 使用 报错 整理

    2024-07-14 09:38:03       26 阅读