3

浅谈C++中的类

 2 years ago
source link: https://www.junz.org/post/cpp_oop_overview/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

类的基本思想

当一个对象被创造出来,就称之为构造.构造的过程实际上是调用了类定义的构造函数

构造函数不能被声明为const

直接初始化构造

这种构造方式调用了初始化构造函数,用参数列表中的参数生成了一个对象

此构造函数可以被重载,有多个,实际调用参数列表最匹配的那个构造函数

std::string str("init")

这里是直接初始化,我们实际上是调用了string类的初始化函数,参数是"init",生成了一个对象

拷贝初始化

利用一个已有的对象初始化另一个对象,称为拷贝初始化

拷贝构造如果需要的话还会进行类型转换,所以一般其不应该为explicit

Foo(const Foo&);

拷贝构造函数的型参应该为引用类型,因为为了调用拷贝构造函数,我们必须拷贝他的实参,然后我们又将调用拷贝构造函数,形成死循环

std::string s1("direct_init");
std::string s2 = s1;

这里是拷贝初始化,我们实际上调用了拷贝构造函数,来生成了一个对象

拷贝赋值运算符

一个已初始化的对象,进行赋值操作时,实际上调用的就是复制运算符

它实际上执行了拷贝构造函数和析构函数的工作

std::string s1("direct_init");
std::string s2;
s2 = s1;

我们可以在参数列表后加上=delete,表示我们禁止拷贝操作

例如iostream阻止了拷贝,避免多个对象写入或读取相同的IO缓冲

Copy can be expensive. --Bjarne Stroustrup

在重新分配内存时,将旧内存拷贝进新元素是不划算的,尤其是旧元素在此之后将不再被使用时

一个更好的办法是移动元素,将资源直接转交给新对象

Foo::Foo(Foo &&f) noexcept : 
	a(f.a), b(f.b) //直接移动资源
	{
	f.a = f.b = nullptr;//源对象之后必须指向不再移动的资源,要保持它进入可析构的状态
	}
移动赋值运算符

移动赋值运算符实际上执行了移动构造函数和析构函数的工作

指必须绑定到右值的引用

它只能绑定到即将被销毁的对象上

右值一般是字面量,或求值过程中临时创建的对象

我们可以显式地将一个左值转换为右值std::move(),于是便可以将右值引用绑定在上面

当一个对象被销毁时,就会自动调用它自身定义的析构函数

以上为类的基本属性,每当使用了一个属性本质上就是调用了相关的函数或方法

编译器的合成行为

如果我们需要编译器生成默认的行为,我们可以在参数列表后架上=default显式地要求生成合成的方法

合成的拷贝构造函数

如果我们没有定义拷贝构造函数,那么编译器会自动生成一个

它实际上是将对象的成员逐一拷贝给另一个对象

  • 如果成员为另一个类,就调用他本身的拷贝构造函数
  • 如果类的成员为内置类型,就直接拷贝
  • 如果成员为数组,就逐元素拷贝成员

合成的移动操作

当我们没有定义拷贝构造函数时,且成员均是可移动时,编译器将自动生成

当我们定义了拷贝构造函数,且无自定义移动行为时,编译器将会把移动操作定义为删除的函数

当我们未拷贝构造函数,且成员不可移动,编译器将会把移动操作定义为删除的函数

public

在整个程序中都能被访问,为接口

private

只可以被类的成员函数访问

protexted

自身和其派生类有权访问

类可以允许其他类或函数访问他的非公有成员,声明了友元即可

类的静态成员

class Foo {
	public:
		static int a;
	private:
		static double b;
}

通常情况下,我们不应该在类的内部初始化类的静态成员

不过我们可以为静态成员提供const整数类型的类内初始值,且要求静态成员必须为constepxr

class Bar {
	static constexpr int a = 10;
}

静态类的成员不与任何对象绑定在一起,也不能被声明为const

int c = Foo::a;

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK