C++之关键字class整理

在C++中,class是一种用户自定义的数据类型,并且可以将数据和函数捆绑在一起,形成一个逻辑实体。class是C++面向对象编程(OOP)的基础,提供了将数据和函数捆绑的方式,让代码更加的模块化、提升了代码的可重用性和易读性。

一、C++ class的定义

class是C++中一个重要的关键字,用它来定义类型,其形式如下:

class ClassName{
public:
// 公共的行为和属性
protected:
// 被保护的行为和属性
private:
// 私有的行为和属性
};

1.1 访问控制

class可以通过访问控制符来限制对成员的访问;C++提供了三种控制级别:public、protected和private。默认情况下,class的成员是私有的,只允许类内部的成员函数(和友元类/函数)访问,但是可以通过使用访问控制符来进行控制调整。

1.2 class的三大特性

C++的class有三大特性:封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism)。
封装: class支持封装,意思就是可以藏逻辑的细节,只提供必要的接口(API)给外部调用。通过将数据私有化并提供公有的访问函数,class通过控制数据的访问操作,从而提高数据安全性。
继承: class可以通过继承来生成新的类(即派生类)。子类(派生类)可以继承父类(基类)的成员(包括数据成员和成员函数),并且可以添加新的成员或覆盖父类的成员。
多态: class的多态性是指允许使用基类的指针或引用来指向派生类的对象,并且可以再运行时动态绑定到正确的函数。多态性是通过虚函数或纯虚函数来(即关键字virtual修饰的函数)实现的。

1.3 成员函数

class可以包含成员函数(即方法或操作),用于处理内部的成员数据。这些成员函数可以访问和修改对象内部的数据,从而执行特定的操作。

1.3.1 构造和析构函数

class中的构造函数和析构函数,用于类对象的初始化和销毁。构造函数在创建对象时被调用,而析构函数则是在对象销毁时被调用,用来释放资源等销毁操作。

class TestClass{
public:
	// 构造函数
	TestClass();
	// 析构函数
	~TestClass();
};

何时使用关键字 explicit ?
explicit可以修饰只有一个参数的构造函数,或者有默认参数的多参数构造函数。当构造函数被explicit修饰后,该构造函数只能显式调用,不能用于隐式类型转换。例如:

class TestClass{
public:
	explicit TestClass(int value){}
	// 或者
	explicit TestClass(int value, int value2 = 0,...){}
	// 或者
	explicit TestClass(int value = 1,...){}
};

int main(){
	TestClass obj = 1; // 错误,不能隐式转换
	TestClass obj2(2); // 正确,显式调用
}

explicit的作用和重要性:

  1. 防止隐式类型转换: explicit关键字可以防止编译器自动将一个类型转换为另一个类型,从而避免潜在的错误和精度丢失。
  2. 提高代码的可读性: 通过明确指定类型转换,可以使代码更加清晰易懂,减少因隐式转换导致的错误。
  3. 避免意外结果: 隐式转换可能会导致意外的结果,使用explicit可以避免这种情况,确保代码能按预期运行。
1.3.2 关键字inline

inline作为C++中的关键字,在函数声明或定义中,在函数返类型前加上关键字inline(这样可以把函数指定为内联函数)。关键字inline的作用主要是用来解决一些频繁调用的函数大量消耗栈空间(栈内存)的问题。需要注意的是,被inline修饰的函数的逻辑不能太复杂,做好不要超过10行代码,不包含循环语句等。

class TestClass{
public:
	inline int add (int a, int b){
		return a + b;
	}
};
1.3.3 虚函数与纯虚函数
1.3.4 重载

重载是在同一个作用域(同一个类内)内存在多个同名函数或操作符的能力,只要它们的参数类型或参数个数不同即可,可以执行多种类型的操作。


class TestClass{
public:
	TestClass(double r = 0.f, double i = 0.f):
		real(r),
		imag(i){

	}

	// 函数重载
	void display(int a){
		std::cout << "Display int: " << a << std::endl;
	}

	// 函数重载
	void display(std::string& a){
		std::cout << "Diaplay string: " << a << std::endl;
	}
	
	// 运算符重载
	TestClass operator+(const TestClass &b){
		TestClass tmp;
		tmp.real = this->real + b.real;
		tmp.imag = this->imag + b.imag;
		return tmp
	}
private:
	double real, imag;
};

需要注意:

  • 参数类型和数量:这是区分重载函数的关键。参数顺序、类型或数量必须不同;
  • 返回类型:仅当参数列表不同时,返回类型不影响重载决议。
  • 友元函数:如果操作符重载需要访问lei的私有成员,通常定位为友元函数。
  • 构造函数重载:类可以有多个构造函数,只要它们的参数列表不同。这是构造函数重载的一个常见用法。
  • 模板和重载:可以将模板和重载结合,创建灵活的通用代码。例如,使用模板函数来处理不同类型的数组元素。
1.3.5 static

在类的内部声明静态函数时,需要用关键字static修饰,但是在类外部定义函数时就不需要了。因为static成员是类的组成部分但不是任何对象的组成部分,所以有以下几个特点:

  1. static函数没有this指针;
  2. static函数不能被声明为const(将成员函数声明为const就是chengnuo不会修改该函数所属的对象);
  3. static成员函数也不能被声明为虚函数。
// .hpp头文件
class TestClass{
public:
	TestClass();
	static int add(int value);
private:
	static int v;
};

// .cpp 源文件
int TestClass::add(int value){
	return TestClass::v + add;
}

1.4 成员变量

class中包含各种数据成员,也可称为类的属性或字段,它们主要用于存储类的属性或状态。它们的数据类型有浮点型、整型、bool型等。

1.4.1 static

static数据成员可以声明为任意类型,可以是常量、引用、数组、类类型等等。
static数据成员必须在类定义的外部定义,并且在定义时进行初始化。
定义该数据成员时,它的定义是在源文件中:

// .hpp 头文件
class TestClass{
public:
	TestClass(){}
private:
	static int value;
	// 特殊的静态常量整型成员
	static const int value2 = 5;
};

// .cpp 源文件
int TestClass::value = 10;

1.5 this指针

在成员函数中有一个附加的隐含形参(即this指针),它由编译器隐含的定义。同时成员函数可以显式使用this指针。

class TestClass{
...
public:
	TestClass(){}
	TestClass& get(){ return *this; }
};

二、继承

继承(inheritance )是面向对象程序设计中代码重复使用的重要手段,它允许程序员在保持原有类特性的基础上进行扩展,增加类型的功能,新生成的类被称为派生类(或子类)。利用继承这一特性,可以体现出面向对象设计的层次结构,体现了从简单到复杂的认知过程。

class Person{
public:
	string name;
	int age;
};

class Student: public Person{
public:
	int _major;
	int _id;
};

“Student“是派生类的名称
“:”表示要继承
“public”表示继承的方式,继承的方式有public、protected、private三种方式
“Person”是基类

继承方式和访问限定符的关系,如下表所示:

类成员/继承方式publicprotectedprivate
public成员publicprotectedprivate
protected成员protectedprotectedprivate
private成员不可见不可见不可见

总结:

  1. 基类中的private成员,虽然也被派生类继承,但是在派生类中是不可见的(即不能去访问)。
  2. 继承时,若不指定继承方式,class默认的继承方式为private,而struct默认的继承方式为public。
  3. 继承的权限排序:public>protected>private。

三、友元

友元,它是允许一个类将其非公有成员的访问权限授予指定的函数或类;不过友元破坏了class的封装性。友元有两种即友元类和友元函数;友元可以卸载class内的任何位置,建议将友元的声明放在类定义的开始或结尾。

关键字friend就是用来声明友元函数的。

class FirendTestClass{
public:
	void test(int value);
};
void test(int value);

class TestClass{
public:
	// 友元类
	friend class FirendTestClass;
	// 友元函数
	frient void FirendTestClass::test(int value);
	frient void test(int value);
};

需要注意的:
1. 友元是单向性的;
2. 友元不具备继承性。

扩展

  1. 一个空类的size为1。
class EmptyClass{
};
std::cout << sizeof(EmptyClass) << std::endl;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值