class object : public base{
public:
object(type1 data1, type2, data2) //这里的 data1 和 data2就是我们下文中的: member initialization list
:base(data1), //这里的base(data1) 和 objdata(data2) 指的是 声明的初始化顺序.
objdata2(data1),
objdata(data2){}
private:
type2 objdata; //这里的 指的是class内数据 成员的声明顺序.
type3 objdata2;
type 4 objdata3; //注意这里没有并没有放入到 声明的初始化顺序.
};
继承体系下的对象构造规则:
1, 记录在member initialization list中的data被按照constructor 声明的初始化顺序 放入,但是 是以class体内数据 成员(data members)的声明顺序 为顺序来进行初始化.
2, 如果一个data member没有出现在初始化列表中,就会调用它的默认构造函数(可能是合成的也可能是自定义的).
3,在 1和2 之前如果 class object 有 virtual table pointer(s), 它们必须被设定为初始值, 指向合适的virtual table(s).
4, 在 1, 2, 3 之前,所有上一层的 base class constructor(s)必须被调用,且:
(1)如果base class constructor被列入当前 class object 声明的初始化列表中,那么任何显式指定的参数都应该被传递进去base class且规则符合1, 2.
(2)如果base class constructor没有被列入当前 class object的初始化列表中,那么调用 base class的默认构造函数.
5, 在1, 2, 3, 4之前,所有的 virtual base class 必须被构造。
demo:
#include <iostream>
class Base {
public:
Base(const int& data)
:x{ data }
{
print();
}
Base() { std::cout << "Base default constructor!" << std::endl; }
virtual ~Base() = default;
Base(const Base& other) :x{ other.x } {}
Base(Base&& other)
:x{ other.x } {}
Base& operator=(const Base& other)
{
this->x = other.x;
return *this;
}
Base& operator=(Base&& other)
{
this->x = std::move(other.x);
return *this;
}
virtual void print()
{
std::cout << "Base x: "<< this->x << std::endl;
}
protected:
int x;
};
class DerBase1 : virtual public Base{
public:
DerBase1(const int& data)
:Base{ data },
y{ data }
{
print(); //调用了虚函数.
}
DerBase1() { std::cout << "DerBase1 default constructor!" << std::endl; }
virtual ~DerBase1() = default;
DerBase1(const DerBase1& other) :Base{ other }, y{ other.y } {}
DerBase1(DerBase1&& other)
:Base{ std::forward<DerBase1>(other) },
y{ other.y } {}
DerBase1& operator=(const DerBase1& other)
{
Base::operator=(other);
this->y = other.y;
return *this;
}
DerBase1& operator=(DerBase1&& other)
{
Base::operator=(std::forward<DerBase1>(other));
this->y = std::move(other.y);
return *this;
}
virtual void print() override //注意这里的: override
{
std::cout << "DerBase1 y: " << this->y << std::endl;
}
protected:
int y;
};
class DerBase2 : virtual public Base {
public:
DerBase2(const int& data)
:Base{ data },
z{ data }
{
print();
}
DerBase2() { std::cout << "DerBase2 default constructor!" << std::endl; }
virtual ~DerBase2() = default;
DerBase2(const DerBase2& other)
:Base{ other },
z{ other.z } {}
DerBase2(DerBase2&& other)
:Base{ std::forward<DerBase2>(other) },
z{ other.z } {}
DerBase2& operator=(const DerBase2& other)
{
Base::operator=(other);
this->z = other.z;
return *this;
}
DerBase2& operator=(DerBase2&& other)
{
Base::operator=(std::forward<DerBase2>(other));
this->z = std::move(other.z);
return *this;
}
virtual void print() override //注意override
{
std::cout << "DerBase2 y: " << this->z << std::endl;
}
protected:
int z;
};
class DDer : public DerBase1, public DerBase2 {
public:
DDer() { std::cout << "DDer default constructor!" << std::endl; }
virtual ~DDer() = default;
DDer(const int& data_)
:DerBase1{ data_ },
DerBase2{ data_ },
data{ data_ }
{
print();
}
DDer(const DDer& other)
:DerBase1{ other },
DerBase2{ other } {}
DDer(DDer&& other)
:DerBase1{ std::forward<DDer>(other) },
DerBase2{ std::forward<DerBase2>(other) },
data(std::move(other.data)){}
DDer& operator=(const DDer& other)
{
DerBase1::operator=(other);
DerBase2::operator=(other);
this->data = other.data;
return *this;
}
DDer& operator=(DDer&& other)
{
DerBase1::operator=(std::forward<DDer>(other));
DerBase2::operator=(std::forward<DDer>(other));
this->data = std::move(other.data);
return *this;
}
virtual void print() override
{
std::cout << "DDer data: " << this->data << std::endl;
}
private:
int data;
};
int main()
{
DerBase1 der1{20};
Base& base = der1;
return 0;
}
通过以上demo我们可以看出来在派生类构造的过程中调用虚函数并不会产生被动态调用! 而且也很容易被人误解. 因此我们在构造函数中调用虚函数的时候最好指明:
比如 DerBase1::print(); 这样进行调用.
也绝对不要在派生类(derived-class)通过static_cast<Base>(*this)把当前派生类转换成基类对象调用基类中的虚函数.虽然能过通过编译,但是这些操作实际上面是在*this的副本上面进行的因此当前this并不会受到影响。
#include <iostream>
class Base{
private:
int number_;
public:
Base()=default;
Base(const int& n_);
virtual void change_data();
void print()const;
void change()noexcept;
virtual ~Base()=default;
};
Base::Base(const int& n_)
:number_(n_)
{
//
}
void Base::change_data()
{
std::cout<<"change number in Base. "<<std::endl;
this->number_ = 999;
}
void Base::print()const
{
std::cout<<"print: "<<this->number_<<std::endl;
}
void Base::change()noexcept
{
std::cout<<"Reset number in Base. "<<std::endl;
this->number_ = 888;
}
class Derived : public Base{
private:
std::string str_;
public:
Derived()=default;
Derived(const std::string& parameter_);
virtual void change_data()override;
~Derived()=default;
};
Derived::Derived(const std::string& parameter_)
:Base(100),
str_(parameter_)
{
//
}
void Derived::change_data()
{
static_cast<Base>(*this).change(); //这里使用了类型转换,然后调用被转换后对象的成员函数。
//虽然*this被转换成了Base, 但是Base的操作实际上是在 *this 的副本上执行的.因此并不会改变当前Derived内的数据内容.
static_cast<Base>(*this).change_data(); //同上.
std::cout<<this->str_<<std::endl;
}
int main()
{
Base first_(0);
Derived second_("shihua");
second_.change_data();
second_.print(); //Base::print(); number = 100.
return 0;
}