Effective C++ 条款01:视 C++ 为一个语言联邦
核心思想:C++ 是由多个子语言组成的联邦,每个子语言有自己的编程范式。理解这些子语言及其规则切换,是写出高效 C++ 代码的关键。
四个子语言及其规则:
- C 语言
- 基础:过程式编程,包含指针、数组、预处理等。
- 规则:按值传递高效(如内置类型)。
- 面向对象 C++
- 核心:类、封装、继承、多态、虚函数。
- 规则:优先按
const
引用传递对象。
- 模板 C++
- 特性:泛型编程、模板元编程。
- 规则:编译期推导类型,需注意依赖类型(
typename
)。
- STL(标准模板库)
- 组件:容器、迭代器、算法、函数对象。
- 规则:迭代器按值传递(类似指针)。
代码示例
1. C 语言部分:内置类型按值传递
#include <iostream>
// 内置类型高效按值传递
void printInt(int val) { // 推荐:直接传递 int
std::cout << "Value: " << val << std::endl;
}
int main() {
int x = 42;
printInt(x); // 高效拷贝
return 0;
}
2. 面向对象 C++:对象按 const
引用传递
#include <string>
class Person {
public:
Person(std::string name) : name_(std::move(name)) {}
virtual ~Person() = default;
virtual std::string role() const { return "Person"; }
protected:
std::string name_;
};
class Student : public Person {
public:
using Person::Person;
std::string role() const override { return "Student"; }
};
// 按 const 引用传递避免拷贝和多态失效
void printRole(const Person& p) { // 正确:支持多态,无拷贝
std::cout << p.role() << std::endl;
}
int main() {
Student s("Alice");
printRole(s); // 输出 "Student"(多态生效)
return 0;
}
3. 模板 C++:使用 typename
声明依赖类型
#include <vector>
template<typename T>
class Container {
public:
using Iterator = typename T::iterator; // 必须用 typename
static Iterator begin(T& container) {
return container.begin();
}
};
int main() {
std::vector<int> vec = {1, 2, 3};
auto it = Container<std::vector<int>>::begin(vec);
return 0;
}
4. STL:迭代器按值传递
#include <vector>
#include <algorithm>
// 迭代器按值传递(类似指针)
template<typename Iter>
void printFirstTwo(Iter begin, Iter end) {
if (begin != end) {
std::cout << *begin << " ";
++begin;
}
if (begin != end) {
std::cout << *begin << std::endl;
}
}
int main() {
std::vector<int> nums = {10, 20, 30};
printFirstTwo(nums.begin(), nums.end()); // 输出 "10 20"
return 0;
}
关键总结
子语言 | 典型场景 | 参数传递规则 |
---|---|---|
C 语言 | 内置类型、指针、数组 | 按值传递 |
面向对象 C++ | 类、继承、虚函数 | 按 const 引用传递 |
模板 C++ | 泛型编程、元编程 | 依赖类型用 typename |
STL | 容器、迭代器、算法 | 迭代器按值传递 |
编程启示:在切换子语言时(如从 STL 迭代器切换到面向对象),需同步切换编程策略,避免效率损失或错误。