为什么调用基本构造函数而不是带参数的构造函数(虚拟继承)?
Why does the base constructor get called instead of the one with parameters (virtual inheritance)?
#include <iostream>
using namespace std;
class Point
{
int x,y;
public:
Point()
{
x=0;
y=0;
}
Point(int x, int y)
{
this->x=x;
this->y=y;
}
Point(Point &p)
{
x=p.x;
y=p.x;
}
friend class Square;
};
class Square
{
Point _point;
int side;
public:
Square() {cout<<"Square.\n";}
Square(Point &p, int side_val): _point(p), side(side_val)
{
cout<<"Square constructor that should be used.\n";
}
};
class Rectangle: public virtual Square
{
int side2;
public:
Rectangle() {}
Rectangle(Point &p, int side_1, int side_2): Square(p,side_1), side2(side_2) {}
};
class Rhombus: public virtual Square
{
Point opposite_point;
public:
Rhombus() {cout<<"Rhombus. \n";}
Rhombus(Point &p, Point &q, int side_1): Square(p, side_1), opposite_point(q)
{
cout<<"Rhombus constructor that should be used \n";
}
};
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2): Rhombus(p,q,side_1),Rectangle(p,side_1,side_2)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
int main()
{
Point down_left(3,5);
Point up_right(2,6);
int side_1=5;
int side_2=7;
Paralellogram par(down_left,up_right,side_1,side_2);
}
我得到的输出是:
Square
Rhombus constructor that should be used
Paralellogram constructor that should be used
我想要做的是实例化一个平行图,它结合了来自菱形和矩形的变量(它应该有一个_point、opposite_point、side、side2),我不想要他们加倍因此我使用虚拟继承。但是我打算使用的 Square 的构造函数永远不会被调用,即使是一次,而是调用基本构造函数。
我该怎么办?放弃虚拟继承?
在虚继承中,虚基是根据最派生的class构造的。
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2) :
Square(), // You have implicitly that
Rectangle(p,side_1,side_2),
Rhombus(p,q,side_1)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
你可能想要
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2) :
Square(p, side_1),
Rectangle(p,side_1,side_2),
Rhombus(p,q,side_1)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
如 Understanding virtual base classes and constructor calls 中所述:
There is always just one constructor call, and always of the actual, concrete class that you instantiate. It is your responsibility to endow each derived class with a constructor which calls the base classes' constructors if and as necessary, as you did in [Rectangle and Rhombus]'s constructor[s].
问问自己:如果 Rectangle
和 Rhombus
调用不同意如何初始化 Square
的唯一(自虚拟)实例怎么办?我们应该听谁的?答案是两者都不是。当前 class,此处 Parallelogram
,始终负责初始化虚拟基地。并且由于这里没有指定构造函数,所以认为Parallelogram
调用了Square
.
的默认构造函数
#include <iostream>
using namespace std;
class Point
{
int x,y;
public:
Point()
{
x=0;
y=0;
}
Point(int x, int y)
{
this->x=x;
this->y=y;
}
Point(Point &p)
{
x=p.x;
y=p.x;
}
friend class Square;
};
class Square
{
Point _point;
int side;
public:
Square() {cout<<"Square.\n";}
Square(Point &p, int side_val): _point(p), side(side_val)
{
cout<<"Square constructor that should be used.\n";
}
};
class Rectangle: public virtual Square
{
int side2;
public:
Rectangle() {}
Rectangle(Point &p, int side_1, int side_2): Square(p,side_1), side2(side_2) {}
};
class Rhombus: public virtual Square
{
Point opposite_point;
public:
Rhombus() {cout<<"Rhombus. \n";}
Rhombus(Point &p, Point &q, int side_1): Square(p, side_1), opposite_point(q)
{
cout<<"Rhombus constructor that should be used \n";
}
};
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2): Rhombus(p,q,side_1),Rectangle(p,side_1,side_2)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
int main()
{
Point down_left(3,5);
Point up_right(2,6);
int side_1=5;
int side_2=7;
Paralellogram par(down_left,up_right,side_1,side_2);
}
我得到的输出是:
Square
Rhombus constructor that should be used
Paralellogram constructor that should be used
我想要做的是实例化一个平行图,它结合了来自菱形和矩形的变量(它应该有一个_point、opposite_point、side、side2),我不想要他们加倍因此我使用虚拟继承。但是我打算使用的 Square 的构造函数永远不会被调用,即使是一次,而是调用基本构造函数。
我该怎么办?放弃虚拟继承?
在虚继承中,虚基是根据最派生的class构造的。
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2) :
Square(), // You have implicitly that
Rectangle(p,side_1,side_2),
Rhombus(p,q,side_1)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
你可能想要
class Paralellogram: public Rectangle, public Rhombus
{
public:
Paralellogram(Point &p, Point &q, int side_1, int side_2) :
Square(p, side_1),
Rectangle(p,side_1,side_2),
Rhombus(p,q,side_1)
{
cout<<"Parallelogram constructor that should be used\n";
}
};
如 Understanding virtual base classes and constructor calls 中所述:
There is always just one constructor call, and always of the actual, concrete class that you instantiate. It is your responsibility to endow each derived class with a constructor which calls the base classes' constructors if and as necessary, as you did in [Rectangle and Rhombus]'s constructor[s].
问问自己:如果 Rectangle
和 Rhombus
调用不同意如何初始化 Square
的唯一(自虚拟)实例怎么办?我们应该听谁的?答案是两者都不是。当前 class,此处 Parallelogram
,始终负责初始化虚拟基地。并且由于这里没有指定构造函数,所以认为Parallelogram
调用了Square
.