C++侯捷学习记录(五)

C++ 下 P13

三个主题

variadic templates (C++ 11)
auto
ranged-base (C++ 11)

reference

在这里插入图片描述加上 const 后 函数签名不同 可以共存

P17 关于vptr 和 vtbl

在这里插入图片描述
子类中有父类 的part 成分 .
当一个类中有虚函数 对象中大小会多一个指针

class  A {
public:
	virtual void fun()
	{

	}
private:
	int x;
	int y;
};
class  B{
public:
	void fun()
	{

	}
private:
	int x;
	int y;
};
int main()
{
	A a;
	B b;
	cout << "A" << sizeof(a) << endl; // 12
	cout << "B" << sizeof(b) << endl;  //8 
	return 0;
}

在这里插入图片描述
虚函数指针 -> 虚函数表 虚函数表中地址指向虚函数
一共四个虚函数 ,四个成员函数
A 中 两个虚函数 一个黄色代表独有的
B 中 两个虚函数 浅蓝色 表示 重写的A 中的 黄色
深蓝色 代表继承了 A 中的 vfun2 函数
C 中 两个虚函数 重写 vfun1
浅黄色代表自己独有的虚函数

静态绑定 调用 call xx
动态绑定 条件 1 通过指针调用 ,2 指针向上转型 比如 new C 但是指针声明的时候 声明的时候是 A .3调用的是虚函数
符合 这三个条件 则成为 动态绑定
具体调用 需要看 p 的指向
多态 虚函数 动态绑定


2020/6/29
虚函数 实现多态的主要途径
在这里插入图片描述
子类对象调用 父类的虚函数 执行到 serialize 时候 跳到 子类对象 ,这是因为动态绑定 this指针指向的是子类对象(谁掉用谁就是this).c++中 成员函数都有 this 这个参数 .
然后调用 this->Seriallize()
编译器 编译成 (*(this->vptr)[n] )(this) ; this 指向子类 所以调用子列的虚函数 ,而不是父类的虚函数
// 非虚函数 定义的对象是啥类型 就调用那个类型函数 看 定义的对象指向谁比如
//A 就调用A 中成员函数
// 虚函数 看具体的对象绑定的是子类 还是父类就是new 的对象指向



class  A {
public:
	virtual void fun1()
	{
		cout << "Afun1\n";
	}
	void fun2()
	{
		cout << "Afun2\n";
	}

};
class  B: public A{
public:
	virtual void fun1()
	{
		cout << "Bfun1\n";
	}
	void fun2()
	{
		cout << "Bfun2\n";
	}
};
int main()
{
	A a;
	a.fun1();    //A
	B b;
	b.fun1();    // B
 	A* ptr = new B;
	// 非虚函数  定义的对象是啥类型 就调用那个类型函数  看 定义的对象指向谁比如
	//A 就调用A 中成员函数
	// 虚函数 看具体的对象绑定的是子类 还是父类就是new 的对象指向谁
	ptr->fun1();   //B
	ptr->fun2();   // A

}
}

在这里插入图片描述

P20 动态绑定

在这里插入图片描述
对象调用成员函数 ,对象是那个类 就调用 那个类的成员函数 ,是静态绑定 比如 图片中 虽然定义为 B 经过强转之后 为A类型
但是 是静态绑定 所以调用的是 A 的虚函数
在这里插入图片描述
动态绑定 必须符合三个条件
1 通过指针调用
2 虚函数
3 向上转形
pa 符合三个条件 所以是动态绑定 call dw…
在这里插入图片描述
const 对象 调用非常量成员函数 编译器会报错.
no-const 都可以调用 成员函数 没有const 和 no -const 区分

new 和 delete 是表达式

在这里插入图片描述

### 关于侯捷 C++ 系列课程学习笔记 #### 内存管理和 `std::allocator` 在探讨内存管理时,`std::allocator` 是一个重要的概念。它提供了一种通用的方式来进行动态内存分配和释放操作[^1]。通过使用 `std::allocator`,可以更灵活地控制容器内部对象的创建与销毁。 ```cpp #include <memory> using namespace std; int main() { allocator<int> alloc; const int n = 1000; int* p = alloc.allocate(n); // 构造元素 uninitialized_fill_n(p, n, 0); // 销毁并回收内存 destroy_n(p, n); alloc.deallocate(p, n); } ``` 这段代码展示了如何利用 `std::allocator` 来手动管理一块整型数据的空间,并对其进行初始化以及最终清理工作。 #### 使用迭代器简化输入处理 对于从标准输入流读取数值并将这些值存储至目标容器的操作,可以通过组合 `istream_iterator` 和算法库中的 `copy()` 函数来实现简洁高效的解决方案[^2]: ```cpp #include <iostream> #include <iterator> #include <vector> #include <algorithm> using namespace std; int main(){ vector<double> c; istream_iterator<double> eos; // 表示结束标记 istream_iterator<double> iit(cin); // 创建基于cin的输入迭代器 copy(iit, eos, back_inserter(c)); // 将所有输入复制到向量c中 } ``` 此程序片段能够方便地接收来自用户的多个浮点数作为输入,并自动将其追加到指定的目标集合内而无需显式循环结构。 #### 移动语义的重要性及其应用 当涉及到像 `std::vector` 这样的序列式容器时,确保自定义类型的移动构造函数和赋值运算符被声明为 `noexcept` 至关重要。这不仅有助于提高性能,还可能影响某些 STL 容器的行为逻辑,比如扩容机制会优先考虑调用 noexcept 的版本以减少异常风险[^3]。 ```cpp class MyClass { public: MyClass(MyClass&& other) noexcept : member(std::move(other.member)) {} MyClass& operator=(MyClass&& other) noexcept { if (this != &other){ member = std::move(other.member); } return *this; } private: string member; }; ``` 上述类实现了无抛出保证的右值引用重载方法,从而使得该类型更适合用于频繁变动大小的数据结构之中。 #### 初始化列表 (`initializer_list`) 及其特性 最后,在介绍现代 C++ 特性的过程中不得不提到 `initializer_list`。这是一种特殊的模板参数形式,允许我们采用花括号语法传递一组同质化的初始值给构造函数或其他接受此类参数的地方[^4]。值得注意的是,尽管看起来像是拥有自己的副本,实际上 initializer_list 并不持有任何实际的对象实例——它仅仅是指向原始数组的一个视图而已。 ```cpp template<typename T> void print(const initializer_list<T>& ilist){ for(auto elem : ilist) cout << elem << " "; } // 调用方式如下所示: print({1, 2, 3}); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值