委托构造和using关键字

委托构造和继承构造

1.委托构造

委托构造函数它可以使用当前的类的其他构造函数来协助当前构造函数的初始化操作。

普通构造函数和委托构造函数区别:

  • 它们两都是一个成员初始值列表与一函数体;
  • 委托构造函数的成员初始值列表只有一个唯一的参数,就是构造函数。

当被委托构造函数当中函数体有代码,那么会先执行完函数体的代码,才加回来到扫托构造函数。

示例

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;

class A
{
public:
	A(int a, string b): _data(a), _str(b)
	{
		cout << "调用普通构造函数" << endl;
	}
	//委托构造函数
	A(int c):A(c,"yy" )
	{
		cout << "调用委托构造函数" << endl;
	}

	void printdata()
	{
		cout << _data << " " << _str << endl;
	}
private:
	int _data;
	string _str;

};



int main()
{
	A obj(20, "xx");
	obj.printdata();
	A obj2(30);
	obj2.printdata();
}

2.using关键字

cpp 复制代码
好的,以下是带有详细注释的完整代码:

## 1. 类型别名 (Type Aliases)

### 替代 `typedef` 的详细注释

```cpp
#include <iostream>
#include <vector>
#include <map>

// 使用 using 创建类型别名,语法:using 别名 = 原始类型;
using Counter = int;          // 给 int 类型起个别名 Counter
using String = std::string;   // 给 std::string 起个别名 String

// 函数指针别名:创建一个函数指针类型的别名
// 这个函数接受两个 int 参数,返回 bool
using Comparator = bool(*)(int, int);

// 实际的比较函数
bool compare(int a, int b) {
    return a < b;
}

int main() {
    // 使用类型别名声明变量
    Counter count = 10;       // 实际上就是 int count = 10
    String name = "Alice";    // 实际上就是 std::string name = "Alice"
    
    // 使用函数指针别名
    Comparator comp = compare;  // comp 现在指向 compare 函数
    std::cout << "比较结果: " << comp(5, 3) << std::endl;  // 输出 0 (false),因为 5 < 3 为假
    
    return 0;
}

模板别名的详细注释

cpp 复制代码
#include <vector>
#include <map>

// 模板类型别名:可以创建带模板参数的类型别名
template<typename T>
using Vec = std::vector<T>;  // Vec<T> 等价于 std::vector<T>

template<typename Key, typename Value>
using Map = std::map<Key, Value>;  // Map<K,V> 等价于 std::map<K,V>

// 更复杂的模板别名例子
template<typename T>
using Pointer = T*;  // Pointer<T> 等价于 T*

int main() {
    // 使用模板别名创建容器
    Vec<int> numbers = {1, 2, 3, 4, 5};  // 等价于 std::vector<int>
    
    // 使用模板别名创建映射
    Map<std::string, int> scores = {
        {"Alice", 95}, 
        {"Bob", 87}
    };  // 等价于 std::map<std::string, int>
    
    // 使用指针别名
    Pointer<int> ptr = new int(42);  // 等价于 int* ptr = new int(42)
    std::cout << "指针指向的值: " << *ptr << std::endl;
    
    delete ptr;  // 释放内存
    
    return 0;
}

2. 命名空间 (Namespace) 的详细注释

引入整个命名空间

cpp 复制代码
#include <iostream>
#include <vector>

// 使用 using namespace 引入整个 std 命名空间
// 这样在代码中就可以直接使用 std 中的名字,不需要写 std::
using namespace std;

int main() {
    // 因为使用了 using namespace std,所以不需要写 std::
    vector<int> numbers = {1, 2, 3};  // 而不是 std::vector<int>
    cout << "Hello World" << endl;    // 而不是 std::cout << "Hello World" << std::endl
    
    return 0;
}

引入特定成员的详细注释

cpp 复制代码
#include <iostream>
#include <vector>

// 只引入 std 命名空间中的特定成员
// 这样既方便使用,又避免了污染全局命名空间
using std::cout;    // 只引入 cout
using std::endl;    // 只引入 endl
using std::vector;  // 只引入 vector

int main() {
    // 可以直接使用引入的成员
    vector<int> numbers = {1, 2, 3};
    cout << "向量大小: " << numbers.size() << endl;
    
    // 但是其他 std 成员仍然需要 std:: 前缀
    // 例如:std::string name;  // 这里还需要 std::
    
    return 0;
}

3. 在类继承中使用的详细注释

改变成员访问权限的详细注释

cpp 复制代码
#include <iostream>

class Base {
private:
    int x = 1;     // 私有成员,只有 Base 类内部可以访问
protected:
    int y = 2;     // 保护成员,Base 和派生类可以访问
public:
    int z = 3;     // 公有成员,任何地方都可以访问
    
    void print() {
        std::cout << "Base - x: " << x << ", y: " << y << ", z: " << z << std::endl;
    }
};

// Derived 私有继承 Base,所有继承来的成员在 Derived 中都变成 private
class Derived : private Base {
public:
    // 使用 using 改变从基类继承来的成员的访问权限
    using Base::y;  // 将 protected 成员 y 在 Derived 中变为 public
    using Base::z;  // 将 public 成员 z 在 Derived 中变为 public
    using Base::print;  // 将 print 方法在 Derived 中变为 public
    
    void show() {
        std::cout << "Derived - y: " << y << ", z: " << z << std::endl;
        // 注意:x 仍然是 private,不能在这里访问
    }
};

int main() {
    Derived d;
    
    // 由于使用了 using,这些成员在 Derived 中都是 public
    d.y = 20;      // 可以访问
    d.z = 30;      // 可以访问
    d.print();     // 可以调用基类的方法
    d.show();      // 可以调用派生类的方法
    
    return 0;
}

解决函数隐藏问题的详细注释

cpp 复制代码
#include <iostream>

class Base {
public:
    // 重载的 func 函数
    void func() {
        std::cout << "Base::func() - 无参数版本" << std::endl;
    }
    
    void func(int x) {
        std::cout << "Base::func(int): " << x << " - 整数参数版本" << std::endl;
    }
};

class Derived : public Base {
public:
    // 如果没有下面的 using 声明,Base 的所有 func 重载都会被隐藏
    // 使用 using Base::func 将基类的所有 func 重载引入到派生类的作用域
    using Base::func;
    
    // 派生类自己的 func 实现
    void func() {
        std::cout << "Derived::func() - 派生类的实现" << std::endl;
    }
    // 注意:这里没有覆盖 func(int),但因为有 using,基类的 func(int) 仍然可用
};

int main() {
    Derived d;
    
    d.func();      // 调用 Derived::func() - 派生类的版本
    d.func(42);    // 调用 Base::func(int) - 基类的版本
    
    // 如果没有 using Base::func; 这一行,d.func(42) 会编译错误
    // 因为派生类的 func() 会隐藏基类的所有 func 重载版本
    
    return 0;
}

4. 类型别名在模板元编程中的应用(详细注释)

cpp 复制代码
#include <iostream>
#include <type_traits>

// 主模板:定义 RemovePointer 类型特征
template<typename T>
struct RemovePointer {
    using type = T;  // 如果 T 不是指针,type 就是 T 本身
};

// 偏特化版本:处理指针类型
template<typename T>
struct RemovePointer<T*> {
    using type = T;  // 如果 T 是指针,type 就是去掉一层指针后的类型
};

// 使用 using 创建模板别名,简化访问
// RemovePointer_t<T> 等价于 typename RemovePointer<T>::type
template<typename T>
using RemovePointer_t = typename RemovePointer<T>::type;

int main() {
    // 测试 RemovePointer_t 类型别名
    
    // int* -> int
    RemovePointer_t<int*> value1 = 42;        // 实际上是 int value1 = 42
    
    // double** -> double* (只去掉一层指针)
    double temp = 3.14;
    double* temp_ptr = &temp;
    RemovePointer_t<double**> value2 = temp_ptr;  // 实际上是 double* value2
    
    std::cout << "value1: " << value1 << std::endl;           // 输出 42
    std::cout << "value2 指向的值: " << *value2 << std::endl; // 输出 3.14
    
    // 更多例子
    RemovePointer_t<int> value3 = 100;        // int -> int
    RemovePointer_t<float*> value4 = 3.14f;   // float* -> float
    
    std::cout << "value3: " << value3 << std::endl;  // 输出 100
    std::cout << "value4: " << value4 << std::endl;  // 输出 3.14
    
    return 0;
}

5. 类型别名与函数指针(详细注释)

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

// 创建函数指针类型的别名,提高代码可读性
using Predicate = bool(*)(int);        // 谓词函数:接受 int,返回 bool
using Transformer = int(*)(int);       // 转换函数:接受 int,返回 int

// 具体的谓词函数:判断数字是否为偶数
bool isEven(int n) { 
    return n % 2 == 0; 
}

// 具体的转换函数:计算平方
int square(int n) { 
    return n * n; 
}

// 处理向量的函数,接受函数指针作为参数
void processVector(std::vector<int>& vec, Predicate pred, Transformer trans) {
    std::cout << "处理前的向量: ";
    for (auto item : vec) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
    
    // 遍历向量,对满足谓词条件的元素应用转换函数
    for (auto& item : vec) {
        if (pred(item)) {           // 如果元素满足谓词条件
            item = trans(item);     // 对元素应用转换函数
        }
    }
    
    std::cout << "处理后的向量: ";
    for (auto item : vec) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 使用函数指针别名传递函数
    processVector(numbers, isEven, square);
    // 处理逻辑:如果是偶数,就计算其平方
    // 1(奇数-不变) 2(偶数->4) 3(奇数-不变) 4(偶数->16) 5(奇数-不变)
    // 结果:1, 4, 3, 16, 5
    
    return 0;
}

关键点总结

  1. 类型别名的优势

    • typedef 语法更清晰
    • 支持模板别名
    • 提高代码可读性
  2. 命名空间使用的建议

    • 在头文件中避免 using namespace
    • 在源文件中可以酌情使用
    • 优先使用 using std::cout 等形式
  3. 继承中的 using

    • 解决函数隐藏问题
    • 调整成员访问权限
    • 保持接口的完整性
  4. 模板编程

    • 简化复杂类型表达式
    • 提高模板代码的可读性
    • 与类型特征(type traits)配合使用
相关推荐
wjm0410062 小时前
ios学习路线 -- Swift基础(1)
开发语言·ios·swift
Vect__2 小时前
深刻理解C++STL库常见容器功能和底层
开发语言·c++
small-pudding2 小时前
深入理解PDF:蒙特卡洛光线追踪中的概率密度函数
算法·pdf·图形渲染
jiang_changsheng2 小时前
VMware 虚拟机无法上网排查解决教程
开发语言·网络·php
历程里程碑2 小时前
Linux 46 HTTPS(协议原理)安全通信全流程解析
linux·网络·c++·网络协议·http·https·排序算法
We་ct2 小时前
LeetCode 46. 全排列:深度解析+代码拆解
前端·数据结构·算法·leetcode·typescript·深度优先·回溯
逆境不可逃2 小时前
LeetCode 热题 100 之 763.划分字母区间
算法·leetcode·职场和发展
MicroTech20252 小时前
微算法科技(NASDAQ:MLGO)量子PBFT改进技术:重构联盟链共识的效率与安全
科技·算法·重构
阿成学长_Cain2 小时前
Windows IP 配置查看器 ipconfig 详解
开发语言·php