c++ primer 学习笔记 第七章 类

第七章 类

  • 定义在类内部的是隐式的inline函数。
  • 成员函数通过一个名为this的隐式参数来访问调用它的那个对象。
//names 类名。total 实例名
name total;
total.isTrue();
//等价于
name::isTrue(&toatal);
  • const关键字放在成员函数的参数列表之后,代表this是一个指向常量的指针,所指对象不可被更改。

类作用域与成员函数

  • 首先编译成员声明,再编译成员函数,因此成员函数可以不用在意类内的成员的声明次序。
  • 返回对象的引用。
return *this;

io类不能被拷贝。

构造函数

  • 构造函数不能被声明成const,毕竟初始化结束前还要向里面写值。
  • 常量对象在其被构造函数初始化完以后才取得常量属性。
  • 当类没有声明任何构造函数时,编译器会自动生成默认构造函数;但是如果自己声明了构造函数,默认构造函数就不会自动生成。
  • 如果类包含有内置类型或复合类型的成员,则只有当这些成员被初始化以后才适用于合成的默认构造函数。

友元

  • class和struct唯一区别就是默认的访问权限。

  • 友元声明只能出现在类的内部,不是类的成员不受其所在区域访问控制级别的约束,只是意思一下这个是我的朋友,可以访问我的私有属性。

  • 友元的声明与类本身放在同一个头文件中(类的外部)。

  • 类和非成员函数的声明不是必须在他们的友元声明之前,甚至在类的内部定义了函数,也得在类外声明使得该函数可见。

class X{
	friend void f(){	/*可以定义在内部*/	};
	X(){
		f();		//错误,f未在外界声明
	}
	void g();
	void h();
};

void X::g(){		//错误,f未在外界声明
	return f();
}

void f(){};
void X::h(){
	return f();		//错误,f未在外界声明
}

void f();
void X::h(){
	return f();		//正确
}

封装

  • 确保用户代码不会无意间破坏封装对象的状态。
  • 被封装的类的具体实现可以随时改变,而无需调整用户级别的代码。

可变数据成员

mutable:即使处于const对象之中也可以被改变。

基于const的重载

class Screen{
public:
	Screen &display(ofstream& os){
		do_display(os);
		return *this;
	}
	const Screen &display(ofstream& os) const{
		do_display(os);
		return *this;
	}
	void do_display(ofstream& os) const{
		os << contens;
	}
}

名字查找与类的作用域

名字查找

  • 首先,在名字所在块中查找其声明语句,只考虑在名字使用之前出现的声明。
  • 如果没找到,继续查找外层作用域。
  • 如果最终没有找到匹配的声明,则程序报错。

类的定义

  • 首先,编译成员的声明。
  • 直到类全部可见后才编译成员函数体。

默认构造函数

#include<bits/stdc++.h>
using namespace std;

class N{
public:
	N(string &){};	//自定义构造函数
	//N(){};		//默认构造函数
};

struct A{
	//A(){};	//默认构造函数
	//N mmem;	//有这条语句后不会再生成默认构造函数
};	
struct B{
	//B(){};
	string b = "10";	//初始化b,传入N(string &);
	N b;
};
int main(){
	A a;
	B b;
}

类类型转换

  • 编译器只会自动执行一步类型转换。
  • explicit抑制类型转换,只对一个实参的构造函数有效。

constexpr构造函数

构造函数不能是const,但字面值常量类的构造函数可以是constexpr函数。

const 和constexpr区别:

  • const 并未区分出编译期常量和运行期常量。

  • constexpr 限定在了编译期常量。

  • constexpr 修饰的函数,返回值不一定是编译期常量。

  • #include<bits/stdc++.h>
    using namespace std;
    
    constexpr int f(int i){
        return ++i;
    }
    int i = 5;
    int a[f(5)];	//正确,传入的5是常量,编译器可得结果,返回的是constexpr
    int b[f(i)];	// 错误,传入的i是变量,需要y计算之后才能知道f的返回值,所以不是constexpr
    
    int main(){
        const int m = 0;
        int n = 0;
        constexpr int i = 10;	//正确
        constexpr int j = i+1;	//正确
        constexpr int k = m+1;	//正确
        constexpr int l = n+1;	//错误
        return 0;
    }
    

constexpr构造函数用于生成constexpr对象以及constexpr函数的参数或返回类型。

类的静态成员

  • 类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。

  • 静态成员函数不与任何对象绑定在一起,它们不包含this指针。

通常情况下,类的静态成员不应该在类的内部初始化。然而,我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr

#include<bits/stdc++.h>
using namespace std;

class Test{
public:
	static int i;		//通常类的静态成员不应该在类的内部初始化
	void show_k(){
		cout << k << ' ';
		kkk(k, i);	//如果不注释,则必须在类外声明k
	}
	void kkk(const int &k, int i){	//如果这个函数不注释,则必须在类外声明k
		cout << k << ' ';
	}
private:
	static constexpr int k = 10;	//可以为静态成员提供const整数类型的类内初始值,要求静
	//态成员必须是字面值常量类型的constexpr 
	static int init_k(){
		return 1;
	};
};

constexpr int Test::k;		//类外声明静态成员k,必须声明。
int Test::i = 0;		//类外定义静态成员

int main(){
	Test a;
	a.show_k();		//正确,调用公有成员访问私有成员
	//cout << a.k;	//错误, 类实例对象不可直接访问私有成员
	//cout << Test::k;    //错误,不可访问类Test私有成员
	cout << Test::i;
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值