类与对象1

1类的定义

cpp 复制代码
class stack
{
public:

private:
	int* _array;
	int _top;
	int _capacity;
};
cpp 复制代码
class Date
{
public:
	void Init(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Init(2010, 12, 30);

	return 0;
}
cpp 复制代码
typedef struct ListNodeC
{
	int val;
	struct ListNodeC* next;
}LNode;
struct ListNodeC
{
	ListNodeC* next;
	int val;
}LTNode;
struct ListNodecpp
{
    //默认是public
	void Init(int x)
	{
		val = x;
		next = nullptr;
	}
	ListNodecpp* next;
	int val;
};

1类的定义格式

class定义类的关键字 stack类的名字 {}中为类的主体 类后面有一个分号不可以省略

类中的内容叫做类的成员

类中的变量叫做类的属性或者类的成员变量

类中的函数叫做类的方法或者类的成员函数

区分成员变量我们通常在变量前面➕ (eg::_array)

C++兼容了C中struct的用法,同时strucrt也可以定义类。struct中也可以定义函数

定义在类里面的函数默认为inline(内联)

2访问限定符

1private protected public

C++实现封装的一种方式 用类将对象的属性和方法结合在一起,对象更加完善,通过访问权限选择性的将其接口给用户使用。

public修饰的成员在类外部可以直接访问,private和protected修饰的成员在类外部不能直接访问到,private protected目前看是一样的,学习继承才会体现出区别。

2访问限定符的作用域

该限定符出现位置开始下一个访问限定符出现位置为止,如果后面没有访问限定符,那么到作用域}即类结束

class中成员默认为private,struct中默认为public

一般成员变量修饰为private,需要给别人使用的成员函数放为public

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

3类域

定义了一个新的作用域,类的所有成员都在这个作用域内,在类外面定义成员,需要使用::(作用域操作符)指明成员属于哪个类域

类域影响编译查找原则

cpp 复制代码
class stack
{
public:

	void Init(int n = 4);//声明

private:
	int* _array;
	int _top;
	int _capacity;
};
void stack::Init(int n)//定义
{
	if (_top == _capacity)
	{
		_array=(int*)malloc(sizeof(int) * n);
		if (_array == nullptr)
		{
			perror("malloc fails");
			return;
		}
		_capacity = n;
		_top = 0;
	}
}
int main()
{
	stack st;
	st.Init();
	return 0;
}

如果上面这个程序Init不指定类域,编译器就会把Init认为是全局函数,编译时就会找不到_array,_top,_capacity这些成员的声明或者定义,就会报错,指定类域stack,就知道Init是成员函数,在当前域找不到_array这些成员,就会到类域中去找。

2类实例化

概念

类类型物理内存中创建对象的过程,叫做类的实例化出对象。

类是对象的一种抽象描述,是模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有开空间,用类实例化出对象才会分配空间

一个类可以实例化出多个对象,实例化出的对象 占用实际的物理内存,存储类成员变量

对象的大小

函数指针

函数指针是一个地址,调用函数就是调用函数编译产生的汇编指令[call]指令,其实函数在编译时就要找到函数的地址,不是在运行时找,只有动态多态是在运行时找,就需要存储函数地址。

cpp 复制代码
class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}
class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;//  p就是类的地址mov ecx p
	p->Print();//call   地址
	
	return 0;
}

成员变量

实例化对象也要符合内存对齐原则

cpp 复制代码
class A
{
public:
	void Print()
	{
		cout << _ch << endl;
	}
private:
	char _ch;
	int _i;
};
class B
{
public:
	void Print()
	{
		//...
	}
};
class C
{
};
int main()
{
	A a;
	B b;
	C c;
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	cout << sizeof(c) << endl;
	return 0;
}
内存对齐规则

1第一个成员在 与结构体偏移量为0的地址处

2其他成员要对齐到对齐数(编译器默认的一个对齐数 与 该成员大小的较小值)的整数倍地址处

vs默认对齐数为8

结构体的总大小:最大对齐数(所有变量类型最大值与默认对齐数取小)的整数倍

3嵌套结构体

嵌套结构体对齐到自己最大对齐数的整数倍

结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)整数倍

3类的默认this指针

引入

当实例化出两个对象d1,d2,当d1调用Init和Print两个函数,该函数是怎么知道访问的是d1对象还是d2对象,c++给了一个隐含的this指针来解决这个问题

编译器编译后,类的成员函数会在形参的第一个位置,增加一个当前类 类型的指针(this指针)

比如 Init的原型是Init(Date* const this,int year,int month,int day)

类的成员函数访问成员变量,本质都是通过this指针访问的比如this->_year=year;

C++规定 this指针在函数的实参和形参部分都不可以显示写(编译器会处理),但是在函数体内可以显示使用this指针

cpp 复制代码
class Date
{
public:
	//void Init(Date* const this,int year,int month,int day)
	//{

	//}
	void Init(int year, int month, int day)
	{
        this->_year=year;
	}
    void Print()
    {
        cout<<_year<<"/"<<_month<<"/"<<_day<<endl;
    }
private:
	int _year;
	int _month;
	int _day;
};
//int main()
//{
//	Data d1;
//	Data d2;
//	d1.Init(2004, 07, 16);
//	d1.Print();
//
//	d2.Init(2005, 9, 16);
//	d2.Print();
//	return 0;
//}

4C语言和C++写栈的区别

cpp 复制代码
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void STInit(ST* ps)
{
	//指向一个存在的表
	assert(ps);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void STDestroy(ST* ps)
{
	//指向一个存在的表
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	//指向一个存在的表
	assert(ps);
	//扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fails");
			exit(1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top++] = x;
}
//判空
bool STEmpty(ST* ps)
{
	////指向一个存在的表
	assert(ps);
	return ps->top == 0;
}

//删除栈顶 
void STPop(ST* ps)
{
	//指向一个存在的表
	assert(ps);
	assert(!STEmpty(ps));
	//assert(ps->top > 0);
	--ps->top;
}

//返回栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	//assert(ps->top > 0);
	return ps->a[ps->top-1];
}

//返回栈元素数目个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

int main()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	//取出栈里面的每一个元素
	while (!STEmpty(&st))
	{
		cout << STTop(&st) << endl;
		STPop(&st);
	}
	STDestroy(&st);
	return 0;
}
class Stack
{
public:
	void Init(int n = 4)
	{
		//指向一个存在的表
		_a =(int*)malloc(sizeof(int) * n);
		_top = _capacity = 0;
	}
	void Destroy()
	{
		//指向一个存在的表
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

	void STPush(int x)
	{
		//指向一个存在的表
		
		//扩容
		if (_top == _capacity)
		{
			int newcapacity =  _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity);
			if (tmp == NULL)
			{
				perror("realloc fails");
				exit(1);
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
	//判空
	bool STEmpty()
	{
		////指向一个存在的表
		
		return _top == 0;
	}

	//删除栈顶 
	void STPop()
	{
		//指向一个存在的表
		assert(_top > 0);
		--_top;
	}

	//返回栈顶元素
	STDataType STTop()
	{
		assert(_top > 0);

		//assert(ps->top > 0);
		return _a[_top - 1];
	}

	//返回栈元素数目个数
	int STSize()
	{

		return _top;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
int main()
{
	Stack st;
	st.Init();
	st.STPush(1);
	st.STPush(2);
	st.STPush(3);
	st.STPush(4);

	while (!st.STEmpty())
	{
		cout << st.STTop() << endl;
		st.STPop();
	}
	st.Destroy();
	return 0;
}
相关推荐
chenyuhao20242 小时前
《C++二叉引擎:STL风格搜索树实现与算法优化》
开发语言·数据结构·c++·后端·算法
空荡forevere3 小时前
《操作系统真象还原》 第十章 输入输出系统
开发语言·c++·操作系统
麦麦鸡腿堡3 小时前
Java的封装
java·开发语言
沢田纲吉4 小时前
《LLVM IR 学习手记(五):关系运算与循环语句的实现与解析》
前端·c++·llvm
沢田纲吉4 小时前
《LLVM IR 学习手记(六):break 语句与 continue 语句的实现与解析》
前端·c++·llvm
爱和冰阔落4 小时前
【C++进阶】继承上 概念及其定义 赋值兼容转换 子类默认成员函数的详解分析
c++
APItesterCris4 小时前
Node.js/Python 实战:编写一个淘宝商品数据采集器
大数据·开发语言·数据库·node.js
余辉zmh5 小时前
【C++篇】:LogStorm——基于多设计模式下的同步&异步高性能日志库项目
开发语言·c++·设计模式
艾莉丝努力练剑5 小时前
【C++STL :list类 (二) 】list vs vector:终极对决与迭代器深度解析 && 揭秘list迭代器的陷阱与精髓
linux·开发语言·数据结构·c++·list