0
点赞
收藏
分享

微信扫一扫

【c++】类和对象基础

热爱生活的我一雷广琴 2022-03-11 阅读 145
c++

类的创建、赋值、权限

#include<iostream>
#include<string>
using namespace std;

class stu {
public:
	//属性  成员属性  成员变量
	string sName;
	int sId;

	//行为  成员函数  成员方法
	void set_sName(string name) {
		sName = name;
	}
	void set_sId(int id) {
		sId = id;
	}
	void showprint() {
		cout << "name:" << sName << "\tid:" << sId << endl;
	}
};

class tea {
	//属性
public:
	string tName;
protected:
	int tId;
private:
	int tWage;

	//方法
public:
	void set_tea(string name, int id, int wage) {
		this->tName = name;
		this->tId = id;
		this->tWage = wage;
	}
	void showprint() {
		cout << "name:" << tName << "\tid:" << tId << "\t\twage:" << tWage << endl;
	}
};

struct test1 {
	int struct_test = 10;//struct 默认权限为公共
};

class test2 {
	int class_test = 10;//class  默认权限为私有
};

void main() {
	stu tony;
	//public类可以这样赋值
	//tony.sName = "tony";
	//tony.sId = 123;

	tony.set_sName("tony");
	tony.set_sId(123);
	tony.showprint();

	tea mary;
	mary.set_tea("mary",101,1000);
	mary.showprint();
	

	test1 a;
	a.struct_test = 0;//可访问
	test2 b;
	//b.struct_test = 0;//不可访问
}

类和对象:初始化和清理

如果不提供构造函数和析构函数,编译器会提供空实现的构造函数和析构函数

class Person {
public://构造函数和析构函数默认是私有的,所以要加public
	Person(){//程序在调用对象时候会自动调用构造
		cout << "我是Person的构造函数" << endl;
	}

	~Person() {//程序在对象销毁前会自动调用析构
		cout << "我是Person的析构函数" << endl;
	}
};

void test(){
	Person p;
}

void main(){
	test();
	system("pause");
	Person person;
	system("pause");
}

构造函数的分类及调用

注意1:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明(返回类型 函数名(),Person p()——错误;)
注意2:不能利用拷贝构造函数初始化匿名对象编译器认为是对象声明

#include<iostream>
using namespace std;

class Person {
public:
	int age;
	int score;

	//普通构造
	Person() {//无参构造
		cout << "无参构造函数!" << endl;
		this->age = 0;
		this->score = 0;		
	}

	Person(int age, int score) {//有参构造
		cout << "有参构造函数!" << endl;
		this->age = age;
		this->score = score;		
	}

	//拷贝构造
	Person(const Person  &p) {
		cout << "拷贝构造函数!" << endl;
		this->age = p.age;
		this->score = p.score;
	}

	void Show() {
		cout << "age:" << age << "\tscore:" << score << endl;
	}

	//~Person() {
	//	cout << "析构函数!" << endl;
	//}
};

//调用有参的构造函数
void test() {

	//括号法,常用
	cout << "*****括号法,常用*****" << endl;
	Person p11; 
	p11.Show();
	Person p12(20,80);
	p12.Show();
	Person p13(p12);
	p13.Show();
	//注意1:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明——返回类型  函数名(),Person p()——错误;

	//显式法
	cout << endl << "*****显式法*****" << endl;
	Person p21 = Person();
	p21.Show();
	Person p22 = Person(20,80);
	p22.Show();
	Person p23 = Person(p22);
	p23.Show();
	//Person(10)单独写就是匿名对象  当前行结束之后,马上析构

	//隐式转换法
	cout << endl << "*****隐式转换法*****" << endl;
	Person p31 = {  };//元素为空或者有多个元素时要用{ },只有一个元素时可以不用{ }直接写元素
	p31.Show();
	Person p32 = { 10, 80 };
	p32.Show();
	Person p33 = p32; 
	p33.Show();

	//注意2:不能利用 拷贝构造函数 初始化匿名对象 编译器认为是对象声明
	//Person p5(p4);
}

void main() {
	test();	
}

拷贝构造函数的调用时机

#include<iostream>
using namespace std;

class Person {
public:
	Person() {
		cout << "无参构造函数!" << endl;
		this->age = 0;
	}
	Person(int age) {
		cout << "有参构造函数!" << endl;
		this->age = age;
	}
	Person(const Person& p) {
		cout << "拷贝构造函数!" << endl;
		this->age = p.age;
	}
	//析构函数在释放内存之前调用
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int age;
};

//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test_a() {
	cout << "*****1.使用一个已经创建完毕的对象来初始化一个新对象" << endl;
	Person man(100); //p对象已经创建完毕
	Person newman(man); //调用拷贝构造函数
	Person newman2 = man; //拷贝构造

	//Person newman3;
	//newman3 = man; //不是调用拷贝构造函数,赋值操作
}

//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {}
void test_b() {
	cout << endl << "*****2.值传递的方式给函数参数传值" << endl;
	Person p; //无参构造函数
	doWork(p);
}

//3. 以值方式返回局部对象
Person doWork2(){
	Person p1;
	cout << (int*)&p1 << endl;
	return p1;
}

void test_c(){
	cout << endl << "*****3.以值方式返回局部对象" << endl;
	Person p = doWork2();
	cout << (int*)&p << endl;
}

void main() {
	test_a();
	test_b;
	test_c();
}

构造函数调用规则

#include<iostream>
using namespace std;

class Person {
public:
	//无参(默认)构造函数
	Person() {
		cout << "无参构造函数!" << endl;
	}
	//有参构造函数
	Person(int a) {
		age = a;
		cout << "有参构造函数!" << endl;
	}
	//拷贝构造函数
	Person(const Person& p) {
		age = p.age;
		cout << "拷贝构造函数!" << endl;
	}
	//析构函数
	~Person() {
		cout << "析构函数!" << endl;
	}
public:
	int age;
};

void test_a()
{
	Person p1(18);
	//如果不写拷贝构造,编译器会自动添加拷贝构造,并且做浅拷贝操作
	Person p2(p1);

	cout << "p2的年龄为: " << p2.age << endl;
}

void test_b()
{
	//如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造
	Person p1; //此时如果用户自己没有提供默认构造,会出错
	Person p2(10); //用户提供的有参
	Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供

	//如果用户提供拷贝构造,编译器不会提供其他构造函数
	Person p4; //此时如果用户自己没有提供默认构造,会出错
	Person p5(10); //此时如果用户自己没有提供有参,会出错
	Person p6(p5); //用户自己提供拷贝构造
}

void main() {
	test_a();
	test_b();
}

深拷贝与浅拷贝

对象中成员含指针时,建议用深拷贝

#include<iostream>
using namespace std;

class Person {
public:
	int age;
	int *height;

	Person() {
		cout << "无参构造" << endl;
	}

	Person(int age, int height) {
		cout << "有参构造" << endl;
		this->age = age;
		this->height = new int(height);//new是在堆区重新开辟一个空间,并返回的是该数据类型的指针
	}

	Person(const Person &p) {
		cout << "拷贝构造" << endl;
		this->age = p.age;
		
		//浅拷贝,对于指针,直接复制指针,没有复制数据(两个对象中的height指针存放的地址相同,指向同一个内存空间)
		//this->height = p.height;//用浅拷贝的时候,在两个对象的指针都释放的时候会报错
		
		//深拷贝,对于指针,先在堆区域复制一个原对象指针指向的数据,再将新对象的指针指向该数据(两个对象中的height指针存放的地址不同,但两个地址的数据相同)
		this->height = new int(*p.height);//用深拷贝时,对象含指针释放的时候也不会报错
	}

	~Person() {
		cout << "析构函数!" << endl;//析构函数将堆区域的变量释放
		if (height != NULL)
		{
			delete height;
			height = NULL;//置空,防止野指针出现
		}
	}
};

void test() {
	Person person(24, 180);
	cout << "person\t\tage:" << person.age << "\thegiht" << *person.height << endl;
	Person new_person(person);
	cout << "new_person\tage:" << person.age << "\thegiht" << *person.height << endl;
}

void main() {
	test();
}

初始对象

#include<iostream>
using namespace std;

class Person {
public:
	int age;
	int height;
	int score;
	Person(int a,int b,int c) :age(a), height(b), score(c) {//方法二初始化列表
	}
	void showprint() {
		cout << "age:" << age << "\t\theight:" << height << "\tscore:" << score << endl;
	}
};

void main() {
	Person person(20,180,85);
	person.showprint();
}

对象成员

#include<iostream>
#include<string>
using namespace std;

class Phone {
public:
	string pname;
	int price;
	Phone() {}
	Phone(string a, int b) :pname(a), price(b) {
		cout << "phone构造函数" << endl;
	}
};

class Person {
public:
	string name;
	Phone myphone;
	Person(string a, string b, int c) :name(a), myphone(b, c) {//这里myphone(b, c)是一个隐式转换法,等价Phone myphone={b,c}
		cout << "person构造函数" << endl;
	}
};

void test() {
	Person person("张三", "华为", 3200);
	cout << "name:" << person.name << "\t\tphone:" << person.myphone.pname << "\t\tprice:" << person.myphone.price << endl;
}

void main() {
	test();
}

静态成员,静态方法

#include<iostream>
#include<string>
using namespace std;

class Person {
public:
	static int static_a;
	int nostatic;
	static void fuc_a() {
		cout << "静态方法fuc_a(puplic)" << endl;
		//nostatic = 100;//静态函数只能访问静态成员,非静态成员的静态函数不能访问
	}

private:
	static int static_b;
	static void fuc_b() {
		cout << "静态方法fuc_b(private)" << endl;
	}
};

int Person::static_a = 0;
int Person::static_b = 0;

void test() {
	//静态成员变量和静态成员方法两种访问方式
	//1、通过对象
	Person person;
	person.static_a = 100;
	//person.static_b = 100;//私有的静态成员不可访问
	cout << "static_a = " << person.static_a << endl;
	person.fuc_a();
	//2、通过类名
	cout << "static_a = " << Person::static_a << endl;
	Person::fuc_a();
	//Person::fuc_b();//私有的静态方法不可访问
}

void main() {
	test();
}

类和对象的大小

#include<iostream>
using namespace std;

class Person_a {};//1B

class Person_b {//4B
	int a;//非静态成员变量
};

class Person_c {//4B
	int a;//非静态成员变量
	static int static_c;//静态成员变量
};
int Person_c::static_c = 0;

class Person_d {//4B
	int a;//非静态成员变量
	static int static_d;//静态成员变量
	void func_() {}
};

void test() {
	//编译器会给空对象分配一个字节空间,为了区分空对象占内存的位置
	cout << "空类占字节数:" << sizeof(Person_a) << endl;
	//非静态成员变量  属于类的对象上
	cout << "(只含非静态成员变量)类占字节数:" << sizeof(Person_b) << endl;
	//静态成员变量    不属于类的对象上
	cout << "(非静态成员变量+静态成员变量)类占字节数:" << sizeof(Person_c) << endl;
	//成员函数        不属于类的对象上
	cout << "(非静态成员变量+静态成员变量+函数)类占字节数:" << sizeof(Person_d) << endl;
}

void main() {
	test();
}

this指针

C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针

const修饰函数和对象

#include<iostream>
using namespace std;

class Person {
public:
public:
	int m_A;
	mutable int m_B; //可修改 可变的

	Person() {
		m_A = 0;
		m_B = 0;
	}

	//this指针的本质是一个指针常量,指针的指向不可修改
	//如果想让指针指向的值也不可以修改,需要声明常函数
	void ShowPerson() const {
		//const Type* const pointer;
		//this = NULL; //不能修改指针的指向 Person* const this;
		//this->mA = 100; //但是this指针指向的对象的数据是可以修改的

		//const修饰成员函数,表示指针指向的内存空间的数据不能修改,除了mutable修饰的变量
		this->m_B = 100;
		cout << "常函数" << endl;
	}

	void MyFunc() {
		//mA = 10000;
		cout << "普通函数"<< endl;
	}
	//const修饰对象  常对象
};
void test() {
		const Person person; //常量对象  
		cout << person.m_A << endl;
		//person.mA = 100; //常对象不能修改成员变量的值,但是可以访问
		person.m_B = 100; //但是常对象可以修改mutable修饰成员变量

		person.ShowPerson();//常对象只能调用常函数

		//常对象访问成员函数
		//person.MyFunc(); //常对象不能调用普通函数
		Person person11;
}
void main() {
	test();
}
举报

相关推荐

0 条评论