个人做网站被骗,vc 做网站源码,华龙网重庆网络问政平台,每太营销咨询一、构造函数的基本分类
1.1 默认构造函数#xff08;Default Constructor#xff09;
没有参数或所有参数都有默认值的构造函数。
class MyClass {
public:// 1. 显式默认构造函数MyClass() {data 0;name default;std::cout Default constr…一、构造函数的基本分类1.1默认构造函数Default Constructor没有参数或所有参数都有默认值的构造函数。class MyClass { public: // 1. 显式默认构造函数 MyClass() { data 0; name default; std::cout Default constructor called\n; } // 2. 编译器生成的隐式默认构造函数 // 如果没有任何构造函数编译器会自动生成 private: int data; std::string name; }; // 使用 MyClass obj1; // 调用默认构造函数 MyClass obj2{}; // C11 统一初始化 MyClass* obj3 new MyClass(); // 动态分配1.2参数化构造函数Parameterized Constructor带有参数的构造函数。class Point { private: double x, y; public: // 参数化构造函数 Point(double xVal, double yVal) { x xVal; y yVal; std::cout Parameterized constructor: ( x , y )\n; } // 带默认值的参数化构造函数 Point(double xVal 0.0, double yVal 0.0, double zVal 0.0) { x xVal; y yVal; std::cout Constructor with defaults called\n; } }; // 使用 Point p1(10.5, 20.3); // 调用参数化构造函数 Point p2(15.0); // 使用默认值 Point p3{}; // 全部使用默认值1.3拷贝构造函数Copy Constructor用同类型的另一个对象初始化新对象。class String { private: char* buffer; size_t length; public: // 普通构造函数 String(const char* str) { length strlen(str); buffer new char[length 1]; strcpy(buffer, str); std::cout Regular constructor: buffer \n; } // 拷贝构造函数深拷贝先申请一个新的内存空间 String(const String other) { length other.length; buffer new char[length 1]; strcpy(buffer, other.buffer); std::cout Copy constructor: buffer \n; } // 拷贝构造函数浅拷贝 - 通常不要这样做 // String(const String other) : buffer(other.buffer), length(other.length) {} ~String() { delete[] buffer; } void print() const { std::cout String: (buffer ? buffer : null) \n; } }; // 使用拷贝构造函数的场景 void demonstrateCopyConstructor() { String s1(Hello); // 普通构造函数 // 场景1直接初始化 String s2(s1); // 拷贝构造函数 String s3 s1; // 拷贝构造函数不是赋值 // 场景2传参 void processString(String str); // 值传递会调用拷贝构造函数 processString(s1); // 场景3返回值 String createString() { String temp(Temp); return temp; // 可能调用拷贝构造函数NRVO优化可能避免 } }1.4移动构造函数Move ConstructorC11将资源从一个临时对象转移到新对象。class DynamicArray { private: int* data; size_t size; public: // 普通构造函数 DynamicArray(size_t n) : size(n), data(new int[n]) { std::fill(data, data size, 0); std::cout Regular constructor, size: size \n; } // 拷贝构造函数 DynamicArray(const DynamicArray other) : size(other.size), data(new int[other.size]) { std::copy(other.data, other.data size, data); std::cout Copy constructor, size: size \n; } // 移动构造函数C11 DynamicArray(DynamicArray other) noexcept : data(other.data), size(other.size) { // 窃取资源 other.data nullptr; // 置空原对象 other.size 0; std::cout Move constructor, size: size \n; } ~DynamicArray() { delete[] data; } // 移动赋值运算符通常与移动构造函数一起实现 DynamicArray operator(DynamicArray other) noexcept { if (this ! other) { delete[] data; // 释放现有资源 data other.data; // 窃取资源 size other.size; other.data nullptr; other.size 0; } return *this; } }; // 使用移动构造函数 void demonstrateMoveConstructor() { DynamicArray arr1(100); // 普通构造函数 // 场景1从临时对象移动 DynamicArray arr2(std::move(arr1)); // 显式移动 // 场景2从函数返回值移动 auto createArray []() - DynamicArray { DynamicArray temp(50); // ... 操作 temp return temp; // 可能调用移动构造函数 }; DynamicArray arr3 createArray(); // 移动构造 // 场景3标准库容器中的移动 std::vectorDynamicArray arrays; arrays.push_back(DynamicArray(30)); // 移动构造 arrays.emplace_back(40); // 原地构造无移动 }1.5委托构造函数Delegating ConstructorC11一个构造函数调用同类的另一个构造函数。class Employee { private: std::string name; int id; double salary; std::string department; public: // 主构造函数包含所有参数 Employee(const std::string n, int i, double s, const std::string d) : name(n), id(i), salary(s), department(d) { std::cout Main constructor called\n; validateData(); } // 委托构造函数委托给主构造函数 Employee(const std::string n, int i, double s) : Employee(n, i, s, Unassigned) { // 委托调用 std::cout Delegating constructor (3 params)\n; } // 另一个委托构造函数 Employee(const std::string n, int i) : Employee(n, i, 0.0, Unassigned) { // 委托调用 std::cout Delegating constructor (2 params)\n; } // 默认构造函数也委托 Employee() : Employee(Unknown, 0, 0.0, Unassigned) { std::cout Default delegating constructor\n; } private: void validateData() { if (salary 0) throw std::invalid_argument(Salary cannot be negative); if (id 0) throw std::invalid_argument(ID cannot be negative); } }; // 使用 Employee e1; // 调用默认委托构造函数 Employee e2(Alice, 1001); // 调用2参数委托构造函数 Employee e3(Bob, 1002, 50000.0); // 调用3参数委托构造函数 Employee e4(Charlie, 1003, 60000.0, Engineering); // 调用主构造函数1.6继承构造函数Inheriting ConstructorC11派生类继承基类的构造函数。class Base { protected: int baseValue; public: Base() : baseValue(0) { std::cout Base default constructor\n; } Base(int val) : baseValue(val) { std::cout Base parameterized constructor: val \n; } Base(int val1, int val2) : baseValue(val1 val2) { std::cout Base two-parameter constructor\n; } }; class Derived : public Base { private: int derivedValue; std::string name; public: // C11之前需要手动重写所有基类构造函数 /* Derived() : Base(), derivedValue(0), name() {} Derived(int val) : Base(val), derivedValue(0), name() {} Derived(int val1, int val2) : Base(val1, val2), derivedValue(0), name() {} */ // C11使用继承构造函数 using Base::Base; // 继承Base的所有构造函数 // 可以添加额外的初始化 Derived() : Base(), derivedValue(0), name(DerivedDefault) { std::cout Derived default constructor\n; } // 也可以定义新的构造函数 Derived(const std::string n) : Base(), derivedValue(0), name(n) { std::cout Derived string constructor: name \n; } void print() const { std::cout Base: baseValue , Derived: derivedValue , Name: name \n; } }; // 使用 Derived d1; // 调用Derived默认构造函数 Derived d2(42); // 调用继承的Base(int)构造函数 Derived d3(10, 20); // 调用继承的Base(int, int)构造函数 Derived d4(Custom); // 调用新的字符串构造函数1.7显式构造函数Explicit Constructor防止隐式类型转换。class SmartPointer { private: int* ptr; public: // 显式构造函数 - 禁止隐式转换 explicit SmartPointer(int* p nullptr) : ptr(p) { std::cout Explicit constructor\n; } // 非显式构造函数 - 允许隐式转换 SmartPointer(int value) : ptr(new int(value)) { std::cout Non-explicit constructor\n; } ~SmartPointer() { delete ptr; } int* get() const { return ptr; } }; class Container { private: SmartPointer sp; public: // 接受SmartPointer参数的构造函数 explicit Container(const SmartPointer s) : sp(s) {} // 接受int指针的构造函数 Container(int* p) : sp(p) {} // 这里会调用SmartPointer的构造函数 }; void demonstrateExplicit() { int* rawPtr new int(42); // 正常使用 SmartPointer sp1(rawPtr); // OK直接初始化 SmartPointer sp2 SmartPointer(rawPtr); // OK显式转换 // 隐式转换被explicit阻止 // SmartPointer sp3 rawPtr; // ❌ 错误不能隐式转换 Container c1(sp1); // OK传递SmartPointer对象 Container c2(rawPtr); // OK调用Container(int*)构造函数 // 隐式转换到SmartPointer再构造Container // Container c3 rawPtr; // ❌ 错误需要两次隐式转换 }二、特殊用途构造函数2.1转换构造函数Conversion Constructor允许从其他类型隐式转换的构造函数。class Complex { private: double real, imag; public: // 转换构造函数从double到Complex Complex(double r, double i 0.0) : real(r), imag(i) { std::cout Conversion constructor: r i i\n; } // 转换构造函数从std::string到Complex Complex(const std::string str) { // 解析字符串如 3.142.71i size_t plusPos str.find(); size_t iPos str.find(i); if (plusPos ! std::string::npos iPos ! std::string::npos) { real std::stod(str.substr(0, plusPos)); imag std::stod(str.substr(plusPos 1, iPos - plusPos - 1)); } else { real std::stod(str); imag 0.0; } std::cout String conversion constructor: str \n; } void display() const { std::cout real imag i\n; } // 类型转换运算符与转换构造函数配对 explicit operator double() const { return real; // 只返回实部 } }; void demonstrateConversion() { Complex c1(3.14); // OK调用转换构造函数 Complex c2 2.71; // OK隐式转换没有explicit // 多个参数的转换 Complex c3 1.0; // imag默认为0 Complex c4 Complex(1.0, 2.0); // 显式调用 // 字符串转换 Complex c5(5.03.0i); // 字符串到Complex Complex c6 std::string(2.0); // 隐式转换 // 在表达式中使用 Complex result c1 10.5; // 10.5被隐式转换为Complex(10.5, 0) // 类型转换运算符 double realPart static_castdouble(c1); // 显式转换 }2.2constexpr 构造函数C11在编译期求值的构造函数。class Point3D { private: double x, y, z; public: // constexpr构造函数 - 可以在编译期调用 constexpr Point3D(double xVal 0.0, double yVal 0.0, double zVal 0.0) : x(xVal), y(yVal), z(zVal) { // constexpr构造函数体必须为空或只包含简单语句 } // constexpr成员函数 constexpr double getX() const { return x; } constexpr double getY() const { return y; } constexpr double getZ() const { return z; } constexpr double distanceSquared() const { return x * x y * y z * z; } // C14起可以在constexpr函数中有更多操作 constexpr void translate(double dx, double dy, double dz) { x dx; y dy; z dz; } }; // 编译期计算 constexpr Point3D origin; // 编译期构造 constexpr Point3D p1(1.0, 2.0, 3.0); // 编译期构造 constexpr double dist p1.distanceSquared(); // 编译期计算 constexpr Point3D p2 []() { // C17起 Point3D p(1.0, 1.0, 1.0); p.translate(1.0, 1.0, 1.0); // (2.0, 2.0, 2.0) return p; }(); // 运行时使用与普通类无区别 Point3D runtimePoint(rand() % 100, rand() % 100, rand() % 100);2.3模板构造函数基于模板参数的构造函数。templatetypename T class Container { private: T* data; size_t capacity; size_t size; public: // 普通构造函数 Container(size_t cap 10) : capacity(cap), size(0) { data new T[capacity]; std::cout Container typeid(T).name() constructor, capacity: capacity \n; } // 模板构造函数从其他类型的Container转换 templatetypename U Container(const ContainerU other) : capacity(other.getCapacity()), size(other.getSize()) { data new T[capacity]; // 转换每个元素 for (size_t i 0; i size; i) { data[i] static_castT(other[i]); } std::cout Template conversion constructor from Container typeid(U).name() \n; } // 模板构造函数从迭代器范围构造 templatetypename InputIt Container(InputIt first, InputIt last) { size capacity std::distance(first, last); data new T[capacity]; std::copy(first, last, data); std::cout Iterator range constructor\n; } ~Container() { delete[] data; } size_t getCapacity() const { return capacity; } size_t getSize() const { return size; } T operator[](size_t index) { return data[index]; } const T operator[](size_t index) const { return data[index]; } }; // 使用模板构造函数 void demonstrateTemplateConstructor() { Containerint intContainer(5); intContainer[0] 1; intContainer[1] 2; // 使用模板转换构造函数 Containerdouble doubleContainer(intContainer); // int - double // 使用迭代器范围构造函数 std::vectorstd::string vec {Hello, World, Template}; Containerstd::string strContainer(vec.begin(), vec.end()); // 从数组构造 int arr[] {10, 20, 30, 40}; Containerint arrContainer(std::begin(arr), std::end(arr)); }2.4显式默认构造函数 defaultC11显式要求编译器生成默认实现。class ModernClass { private: std::string name; int id; std::vectordouble values; public: // 显式默认构造函数 ModernClass() default; // 参数化构造函数 ModernClass(const std::string n, int i) : name(n), id(i) {} // 显式默认拷贝构造函数 ModernClass(const ModernClass) default; // 显式默认移动构造函数 ModernClass(ModernClass) default; // 显式默认析构函数 ~ModernClass() default; // 显式默认拷贝赋值运算符 ModernClass operator(const ModernClass) default; // 显式默认移动赋值运算符 ModernClass operator(ModernClass) default; // 删除特定函数 ModernClass(int) delete; // 禁止从int构造 void display() const { std::cout Name: name , ID: id , Values count: values.size() \n; } }; // 对比传统写法 class TraditionalClass { private: std::string name; int id; std::vectordouble values; public: // 传统写法需要手动实现所有特殊成员函数 TraditionalClass() {} // 空实现 TraditionalClass(const TraditionalClass other) : name(other.name), id(other.id), values(other.values) {} TraditionalClass(TraditionalClass other) noexcept : name(std::move(other.name)), id(other.id), values(std::move(other.values)) { other.id 0; } ~TraditionalClass() {} // 空析构函数 TraditionalClass operator(const TraditionalClass other) { if (this ! other) { name other.name; id other.id; values other.values; } return *this; } TraditionalClass operator(TraditionalClass other) noexcept { if (this ! other) { name std::move(other.name); id other.id; values std::move(other.values); other.id 0; } return *this; } };2.5显式删除构造函数 deleteC11禁止特定的构造函数。class NonCopyable { private: int* resource; public: NonCopyable(int value 0) : resource(new int(value)) { std::cout NonCopyable constructor: value \n; } // 删除拷贝构造函数 - 禁止拷贝 NonCopyable(const NonCopyable) delete; // 删除拷贝赋值运算符 NonCopyable operator(const NonCopyable) delete; // 允许移动 NonCopyable(NonCopyable other) noexcept : resource(other.resource) { other.resource nullptr; std::cout NonCopyable move constructor\n; } NonCopyable operator(NonCopyable other) noexcept { if (this ! other) { delete resource; resource other.resource; other.resource nullptr; } return *this; } ~NonCopyable() { delete resource; } int getValue() const { return resource ? *resource : -1; } }; class Singleton { private: static Singleton* instance; int data; // 私有构造函数 - 禁止外部创建 Singleton() : data(0) {} // 删除拷贝和移动构造函数 Singleton(const Singleton) delete; Singleton(Singleton) delete; Singleton operator(const Singleton) delete; Singleton operator(Singleton) delete; public: static Singleton getInstance() { if (!instance) { instance new Singleton(); } return *instance; } void setData(int val) { data val; } int getData() const { return data; } // 注意需要单独实现清理逻辑 static void destroy() { delete instance; instance nullptr; } }; // 使用 void demonstrateDeletedConstructors() { NonCopyable nc1(42); // NonCopyable nc2 nc1; // ❌ 错误拷贝构造函数被删除 // nc2 nc1; // ❌ 错误拷贝赋值被删除 NonCopyable nc3 std::move(nc1); // ✅ 允许移动 Singleton s1 Singleton::getInstance(); // Singleton s2 s1; // ❌ 错误拷贝构造函数被删除 // Singleton s3; // ❌ 错误构造函数私有 }三、构造函数的特殊特性3.1初始化列表Initializer List在构造函数体执行前初始化成员。class InitializationDemo { private: const int constMember; // 必须在初始化列表初始化 int refMember; // 必须在初始化列表初始化 int normalMember; std::string strMember; std::vectorint vecMember; public: // 正确的初始化列表 InitializationDemo(int x, int ref, const std::string str) : constMember(x), // 常量成员 refMember(ref), // 引用成员 normalMember(0), // 普通成员 strMember(str), // 类类型成员 vecMember{1, 2, 3, 4} { // 使用初始化列表初始化vector // 构造函数体 normalMember 10; // 可以在构造函数体中赋值 // constMember 20; // ❌ 错误常量成员不能在构造函数体中赋值 // refMember ref; // ❌ 错误引用必须在初始化列表初始化 } // 初始化顺序取决于成员声明顺序而不是初始化列表顺序 class OrderMatters { int a; int b; public: // 危险初始化顺序是a先于b但列表中是b先于a OrderMatters(int val) : b(val), a(b 1) { // a(b1)先执行但b未初始化 std::cout a a , b b \n; } }; void display() const { std::cout constMember: constMember , refMember: refMember , normalMember: normalMember , strMember: strMember , vec size: vecMember.size() \n; } };3.2noexcept 构造函数声明构造函数不会抛出异常。class NoThrowClass { private: std::unique_ptrint[] data; size_t size; public: // noexcept构造函数 - 承诺不抛出异常 NoThrowClass(size_t n) noexcept : data(std::make_uniqueint[](n)), size(n) { // 这里不能抛出异常否则程序会调用std::terminate std::fill(data.get(), data.get() size, 0); } // 移动构造函数也应该是noexcept NoThrowClass(NoThrowClass other) noexcept : data(std::move(other.data)), size(other.size) { other.size 0; } // noexcept的重要性标准库容器在重新分配内存时会使用移动 // 如果移动构造函数不是noexcept则会使用拷贝 // 标记可能抛出异常的构造函数 NoThrowClass(const std::string filename) : data(nullptr), size(0) { // 文件操作可能抛出异常 std::ifstream file(filename); if (!file) { throw std::runtime_error(Cannot open file); } // ... 读取数据 } }; // 使用noexcept构造函数 void demonstrateNoexcept() { std::vectorNoThrowClass objects; // 由于移动构造函数是noexceptvector重新分配时会使用移动 for (int i 0; i 100; i) { objects.emplace_back(100); // 高效移动不会拷贝 } }3.3私有/受保护构造函数控制对象的创建方式。class FactoryPattern { private: int id; std::string type; // 私有构造函数 - 只能通过工厂方法创建 FactoryPattern(int i, const std::string t) : id(i), type(t) {} public: // 工厂方法 static std::unique_ptrFactoryPattern createObjectA(int id) { return std::make_uniqueFactoryPattern(id, TypeA); } static std::shared_ptrFactoryPattern createObjectB(int id) { return std::make_sharedFactoryPattern(id, TypeB); } static FactoryPattern createObjectC(int id) { return FactoryPattern(id, TypeC); // C17起保证RVO } // 也可以创建不同子类 class SubTypeA : public FactoryPattern { private: SubTypeA(int id) : FactoryPattern(id, SubTypeA) {} public: static std::unique_ptrSubTypeA create(int id) { return std::make_uniqueSubTypeA(id); } }; }; class BuilderPattern { private: std::string name; int value; double factor; // 私有构造函数 - 只能通过Builder创建 BuilderPattern(const std::string n, int v, double f) : name(n), value(v), factor(f) {} public: // Builder类 class Builder { private: std::string name; int value 0; double factor 1.0; public: Builder setName(const std::string n) { name n; return *this; } Builder setValue(int v) { value v; return *this; } Builder setFactor(double f) { factor f; return *this; } BuilderPattern build() { if (name.empty()) { throw std::invalid_argument(Name cannot be empty); } return BuilderPattern(name, value, factor); } }; static Builder createBuilder() { return Builder(); } void display() const { std::cout Name: name , Value: value , Factor: factor \n; } }; // 使用 void demonstratePrivateConstructors() { // Factory模式 auto obj1 FactoryPattern::createObjectA(1); auto obj2 FactoryPattern::createObjectB(2); auto obj3 FactoryPattern::createObjectC(3); auto subObj FactoryPattern::SubTypeA::create(4); // Builder模式 auto builder BuilderPattern::createBuilder(); auto builtObj builder.setName(Test) .setValue(100) .setFactor(2.5) .build(); builtObj.display(); }四、构造函数的高级应用4.1完美转发构造函数templatetypename T class Wrapper { private: T wrappedObject; public: // 完美转发构造函数 templatetypename... Args explicit Wrapper(Args... args) : wrappedObject(std::forwardArgs(args)...) { std::cout Wrapper perfect-forwarding constructor\n; } // 拷贝构造函数需要单独定义否则模板会覆盖 Wrapper(const Wrapper other) : wrappedObject(other.wrappedObject) { std::cout Wrapper copy constructor\n; } // 移动构造函数 Wrapper(Wrapper other) noexcept : wrappedObject(std::move(other.wrappedObject)) { std::cout Wrapper move constructor\n; } const T get() const { return wrappedObject; } T get() { return wrappedObject; } }; // 使用完美转发 void demonstratePerfectForwarding() { // 各种构造方式都能正确转发 Wrapperstd::string ws1(Hello); // 从const char*构造 Wrapperstd::string ws2(5, A); // 从count和char构造 Wrapperstd::vectorint wv1{1, 2, 3, 4}; // 初始化列表 Wrapperstd::vectorint wv2(10, 42); // 从count和value构造 // 自定义类型 class ComplexType { public: ComplexType(int a, double b, const std::string c) { std::cout ComplexType constructor\n; } }; WrapperComplexType wc(42, 3.14, test); // 完美转发多个参数 }4.2SFINAE 约束的构造函数templatetypename T class SmartContainer { private: std::vectorT data; public: // SFINAE只有T可默认构造时才启用此构造函数 templatetypename U T, typename std::enable_if_tstd::is_default_constructible_vU SmartContainer(size_t size) : data(size) { std::cout Default value constructor, size: size \n; } // 只有T可拷贝构造时才启用 templatetypename U T, typename std::enable_if_tstd::is_copy_constructible_vU SmartContainer(size_t size, const T value) : data(size, value) { std::cout Fill constructor, size: size \n; } // 只有T可从迭代器构造时才启用 templatetypename InputIt, typename std::enable_if_t std::is_constructible_vT, typename std::iterator_traitsInputIt::value_type SmartContainer(InputIt first, InputIt last) : data(first, last) { std::cout Iterator range constructor\n; } // C20概念更简洁 /* SmartContainer(size_t size) requires std::default_initializableT : data(size) {} SmartContainer(size_t size, const T value) requires std::copyableT : data(size, value) {} templatestd::input_iterator InputIt SmartContainer(InputIt first, InputIt last) : data(first, last) {} */ }; // 使用SFINAE构造函数 void demonstrateSFINAE() { // 对于可默认构造的类型 SmartContainerint sci1(10); // 调用默认值构造函数 SmartContainerint sci2(10, 42); // 调用填充构造函数 // 对于不可默认构造的类型 class NoDefault { public: NoDefault() delete; NoDefault(int) {} }; SmartContainerNoDefault scn1(10, NoDefault(42)); // OK填充构造 // SmartContainerNoDefault scn2(10); // ❌ 错误没有默认构造函数 }五、构造函数调用顺序总结class Base { public: Base() { std::cout Base constructor\n; } virtual ~Base() { std::cout Base destructor\n; } }; class Member { public: Member() { std::cout Member constructor\n; } ~Member() { std::cout Member destructor\n; } }; class Derived : public Base { private: Member member; int value; public: // 构造顺序 // 1. 基类构造函数 // 2. 成员变量构造函数按声明顺序 // 3. 派生类构造函数体 Derived(int v) : Base(), value(v) { // 初始化列表顺序不影响实际顺序 std::cout Derived constructor, value value \n; } // 析构顺序相反 // 1. 派生类析构函数体 // 2. 成员变量析构函数按声明顺序的逆序 // 3. 基类析构函数 ~Derived() { std::cout Derived destructor\n; } }; // 多重继承 class Base1 { public: Base1() { std::cout Base1 constructor\n; } }; class Base2 { public: Base2() { std::cout Base2 constructor\n; } }; class MultipleDerived : public Base1, public Base2 { public: // 构造顺序 // 1. Base1构造函数 // 2. Base2构造函数 // 3. MultipleDerived构造函数体 MultipleDerived() { std::cout MultipleDerived constructor\n; } }; // 虚继承 class VirtualBase { public: VirtualBase() { std::cout VirtualBase constructor\n; } }; class VirtualDerived1 : virtual public VirtualBase { public: VirtualDerived1() { std::cout VirtualDerived1 constructor\n; } }; class VirtualDerived2 : virtual public VirtualBase { public: VirtualDerived2() { std::cout VirtualDerived2 constructor\n; } }; class DiamondDerived : public VirtualDerived1, public VirtualDerived2 { public: // 虚基类只构造一次 // 构造顺序 // 1. VirtualBase构造函数虚基类优先 // 2. VirtualDerived1构造函数 // 3. VirtualDerived2构造函数 // 4. DiamondDerived构造函数体 DiamondDerived() { std::cout DiamondDerived constructor\n; } };