C++面向对象(一):类、封装、成员变量初始化

本文介绍了C++中的面向对象特性,包括类的声明与实现,封装原则以及成员变量的初始化。讲解了class与struct的区别,强调了封装的重要性,并探讨了如何通过构造函数确保成员变量的初始化。

C++面向对象(一):类、封装、成员变量初始化

C++中的类

C++可以使用 classstruct 来定义类。

class是C++特有的,C里面没有,至于为什么要保留sturct,大概是为了让开发者更顺滑的从C过渡到C++吧。

#include <iostream>
using namespace std;
// struct Person {
class Person {
public:
  // 属性(成员变量)
	int m_age;
	const char *m_name;
  // 自定义构造函数,进行初始化,可以重载
  // this可以省略,在编译时会自动加上,指向对象
	Person () {
		this->m_name = "卢本伟";
		m_age = 666;
	}
  // 自定义构造函数,简写
	Person (const char *name, int age) :m_name (name), m_age (age) {}
  // 方法(成员函数)
	void say () {
		cout << "my name is " << this->m_name << ", I am " << m_age << " years old." << endl;
		cout << m_name << " NB!" << endl;
	}
   //析构函数
   // 在里面释放一些资源
	~Person () {
		cout << this->m_name << "已经被释放" << endl;
	}
};

与C 相比,C++中 struct 定义的类里面可以定义函数,在C中,可以这样模拟成员函数:

void test() {};
struct Person {
	void(*say)() = test;
};

C++中利用类创建一个对象,并调用属性与方法:

void test () {
	// 利用类创建对象
	Person person;
	// Java\Js :
	// Person person = new Person();
	// OC :
	// Person *person = [Person new];
    
	//访问属性与方法
	person.m_name = "伞兵一号";
	person.m_age = 666;
	person.say ();
	cout << "**********************" << endl;
	// 把person对象的地址值给指针,所以指针对象的类型是Person
	Person *p = &person;
	p->m_name = "伞兵二号";
	p->m_age = 233;
	p->say ();
	cout << "**********************" << endl;

	{
		// 直接创建一个实例,再对实例初始化
		// 这里在栈上实例化,没有任何东西就调用默认构造函数
		Person lubenwei;
		lubenwei.m_age = 666666;
		lubenwei.say ();
	}
	cout << "**********************" << endl;
	{	// 堆上构建
	   // new返回一个指针
		Person* lu = new Person ("伞兵三号", 250);
		// 指针调用
		lu->say ();
		// 对象对用
		//(*lu).say();
		delete lu;
	}
}

structclass的区别在于权限:

struct的默认成员权限是public,外面所有人可以直接访问。

class的默认成员权限是private,只有类内部可以访问。

这两个是一样的:

class Person {
//public:
  // 属性(成员变量)
	int m_age;
	const char *m_name;
  // 方法(成员函数)
	void say () {
		cout << m_name << "NB!" << endl;
	}
};

struct Person {
private:
  // 属性(成员变量)
	int m_age;
	const char *m_name;
  // 方法(成员函数)
	void say () {
		cout << m_name << "NB!" << endl;
	}
};

C++中一般创建类还是使用class较多。

class Person {
public:
    int m_age;
    void say() {
        cout << m_age << endl;
    }
};
void test () {
    Person person;
    person *p = &person;
    p->m_age = 250;
    p->say();
}

上面这段代码中的person对象、p指针都存在于函数的栈空间中,自动分配和回收。

x64环境下,这里的person对象占4个字节(只有一个int属性),p指针占8个字节(指向person的地址值),局部变量总共占用12个字节。

struct Car {
	int m_price;
};
class Car {
public:
	int m_price;
};
int main() {
	Car car;
	car.m_price = 1;
	getchar();
	return 0;
}

这里的car对象就只有一个成员,并且占用4个字节,所以car对象的地址值就是m_price的地址值,可以看一下这里structclass生成的汇编,除了地址之外,两句是一模一样的,所以这两个实际上确实只有权限区别。

00007FF640DA60CF  mov         dword ptr [rbp+4],1
00007FF7694360CF  mov         dword ptr [rbp+4],1

每次创建成员变量都会分配内存,而函数在内存中只有一份,不管创建几个对象都只会call那个相同的函数地址,执行相同的代码,并且由于编译器优化的原因,函数没有调用时是不被编译的,相当于不存在。

声明和实现分离

开发时会将类的声明和实现分离。

声明放入头文件:

// 放入.h文件
class Person {
private:
	int m_age;
public:
	// 一些声明
	Person();
	void setAge(int age);
	int getAge();
	~Person();
};

实现在cpp文件:

#include "Person.h"
// 加一个域限定符::
void Person::setAge(int age) { 
	m_age = age; 
}
int Person::getAge() {
	return m_age;
}
Person::Person(){
	m_age = 0;
}
Person::~Person() {
}

封装

成员变量私有化,提供公共的getter和setter给外界访问成员变量

为了防止外部的随意篡改,而在类内部进行处理:

class Person {
	int m_id = 1;
	int m_age = 2;
	int m_height = 3;
	void display() {
		cout << "m_id is " << m_id << endl;
		cout << "m_age is " << m_age << endl;
		cout << "m_height is " << m_height << endl;
	}
public :
    // 赋值
	void setAge(int age) {
		if (age <= 0) {
			m_age = 666;
		} else {
			m_age = age;
		}
	}
    // 取值
	int getAge() {
		return m_age;
	}

};

int main() {
	Person person;
	person.setAge(-666);
	int age = person.getAge();
	cout << age << endl;
	getchar();
	return 0;
}

成员变量初始化

没有自定义构造函数时:

struct Person {
	int m_age;
};

// 全局区:成员变量初始化为0
// 全局区的变量都会初始化为0
Person g_person;

int main() {

	// 栈空间:没有初始化成员变量,会报错
	// Person person;

	// 堆空间:没有初始化成员变量
	Person *p0 = new Person;
    // 堆空间:成员变量初始化为0
	Person *p1 = new Person();
	// 堆空间:没有初始化成员变量
	Person *p2 = new Person[6];
	// 堆空间:6个Person对象的成员变量全部初始化为0
	Person *p3 = new Person[6]();
	// 堆空间:6个Person对象的成员变量全部初始化为0
	Person *p4 = new Person[6]{};
    
	getchar();
	return 0;
}

但是,如果定义了构造函数,除了全局区,其他内存空间的成员变量默认都不会被初始化,需要开发人员手动初始化。

快捷的初始化所有对象:

struct Person {
	int m_age;
	Person () {
	// 希望创建的所有对象的成员变量全部初始化为0
		memset(this, 0, sizeof(Person));
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值