从两个相同的派生 class 中派生出 class
Derive a class from two same-Derived classes
exercise.h如下
#ifndef EXERCISE_H_
#define EXERCISE_H_
// ROOT namespace
namespace root{
// USHORT definition
typedef unsigned short ushort;
// PI DEFINITION
const double PI = 3.141592;
class shape {
double height;
double width;
public:
shape(double h = 1, double w = 1);
virtual ~shape(){}
double getHeight() const;
double getWidth() const;
virtual double area() const = 0;
};
class rectangle : virtual public shape{
public:
rectangle(double height = 1, double width = 1);
double area() const;
};
class triangle : virtual public shape {
public:
triangle(double h = 1, double w = 1);
double area() const;
};
class someShape : public rectangle, public triangle{
public:
someShape(double rh = 1, double rw = 1, double th = 2, double tw = 2);
double area() const;
double trySomething() const;
};
} // NAMESPACE
#endif /* EXERCISE_H_ */
exercise.cpp是这样的
#include <iostream>
#include <cmath>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
using root::ushort;
// BEGIN SHAPE CLASS
root::shape::shape(double h, double w) : height(h), width(w){
}
double root::shape::getHeight() const{
return this->height;
}
double root::shape::getWidth() const{
return this->width;
}
// END SHAPE CLASS
// BEGIN RECTANGLE CLASS
root::rectangle::rectangle(double h, double w) : shape(h,w){
}
double root::rectangle::area() const{
return this->getHeight() * this->getWidth();
}
// END RECTANGLE CLASS
// BEGIN TRIANGNLE CLASS
root::triangle::triangle(double h, double w) : shape(h,w){
}
double root::triangle::area() const{
return this->getHeight() * this->getWidth() / 2;
}
// END TRIANGLE CLASS
root::someShape::someShape(double rh, double rw, double th, double tw) : rectangle(rh,rw), triangle(th,tw){
}
double root::someShape::area() const {
return rectangle::area();
}
double root::someShape::trySomething() const{
return triangle::getHeight() * rectangle::getWidth();
}
主要
#include <iostream>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
int main(){
root::shape *ptrShape;
ptrShape = new root::someShape(3,2,4,3);
cout << "shape area: " << ptrShape->area() << endl;
delete ptrShape;
}
当我创建一个 someShape 对象时,我只获得了默认值。尽管我初始化了派生 class。还有一件事。事实上,我们分别派生了 Rectangle 和 Triangle,并从这些对象派生了另一个对象。编译器将如何决定使用哪个 area() 函数?
这里的问题是你有一个从 shape
到 rectangle
和 triangle
的虚拟继承,所以 rectangle
和 triangle
的构造函数确实未初始化 shape
。您的 someShape
构造函数等同于:
root::someShape::someShape(double rh, double rw, double th, double tw) :
rectangle(rh,rw), triangle(th,tw), shape() {
}
这就是您获得默认值 1
和 1
的原因。另外请注意,由于您具有虚拟继承,因此您不能为矩形和三角形存储不同的 height
和 width
。你的构造函数应该是这样的:
root::someShape::someShape(double h, double w) :
rectangle(h, w), triangle(h, w), shape(h, w) {
}
或者如果您不想拥有 shape
的单个实例,您应该删除 rectangle
和 triangle
.
的虚拟继承
另见 c++ virtual inheritance。
问题是您正在执行虚拟继承,即矩形和三角形使用 virtual 关键字继承形状。因此,派生的 classes 共享形状 class 的单个实例。因此,编译器完全跳过了从矩形和三角形到形状的构造函数调用。
检查此以了解更多详细信息:
http://www.cprogramming.com/tutorial/virtual_inheritance.html
https://isocpp.org/wiki/faq/multiple-inheritance
exercise.h如下
#ifndef EXERCISE_H_
#define EXERCISE_H_
// ROOT namespace
namespace root{
// USHORT definition
typedef unsigned short ushort;
// PI DEFINITION
const double PI = 3.141592;
class shape {
double height;
double width;
public:
shape(double h = 1, double w = 1);
virtual ~shape(){}
double getHeight() const;
double getWidth() const;
virtual double area() const = 0;
};
class rectangle : virtual public shape{
public:
rectangle(double height = 1, double width = 1);
double area() const;
};
class triangle : virtual public shape {
public:
triangle(double h = 1, double w = 1);
double area() const;
};
class someShape : public rectangle, public triangle{
public:
someShape(double rh = 1, double rw = 1, double th = 2, double tw = 2);
double area() const;
double trySomething() const;
};
} // NAMESPACE
#endif /* EXERCISE_H_ */
exercise.cpp是这样的
#include <iostream>
#include <cmath>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
using root::ushort;
// BEGIN SHAPE CLASS
root::shape::shape(double h, double w) : height(h), width(w){
}
double root::shape::getHeight() const{
return this->height;
}
double root::shape::getWidth() const{
return this->width;
}
// END SHAPE CLASS
// BEGIN RECTANGLE CLASS
root::rectangle::rectangle(double h, double w) : shape(h,w){
}
double root::rectangle::area() const{
return this->getHeight() * this->getWidth();
}
// END RECTANGLE CLASS
// BEGIN TRIANGNLE CLASS
root::triangle::triangle(double h, double w) : shape(h,w){
}
double root::triangle::area() const{
return this->getHeight() * this->getWidth() / 2;
}
// END TRIANGLE CLASS
root::someShape::someShape(double rh, double rw, double th, double tw) : rectangle(rh,rw), triangle(th,tw){
}
double root::someShape::area() const {
return rectangle::area();
}
double root::someShape::trySomething() const{
return triangle::getHeight() * rectangle::getWidth();
}
主要
#include <iostream>
#include "exercise.h"
using std::cout;
using std::cin;
using std::endl;
int main(){
root::shape *ptrShape;
ptrShape = new root::someShape(3,2,4,3);
cout << "shape area: " << ptrShape->area() << endl;
delete ptrShape;
}
当我创建一个 someShape 对象时,我只获得了默认值。尽管我初始化了派生 class。还有一件事。事实上,我们分别派生了 Rectangle 和 Triangle,并从这些对象派生了另一个对象。编译器将如何决定使用哪个 area() 函数?
这里的问题是你有一个从 shape
到 rectangle
和 triangle
的虚拟继承,所以 rectangle
和 triangle
的构造函数确实未初始化 shape
。您的 someShape
构造函数等同于:
root::someShape::someShape(double rh, double rw, double th, double tw) :
rectangle(rh,rw), triangle(th,tw), shape() {
}
这就是您获得默认值 1
和 1
的原因。另外请注意,由于您具有虚拟继承,因此您不能为矩形和三角形存储不同的 height
和 width
。你的构造函数应该是这样的:
root::someShape::someShape(double h, double w) :
rectangle(h, w), triangle(h, w), shape(h, w) {
}
或者如果您不想拥有 shape
的单个实例,您应该删除 rectangle
和 triangle
.
另见 c++ virtual inheritance。
问题是您正在执行虚拟继承,即矩形和三角形使用 virtual 关键字继承形状。因此,派生的 classes 共享形状 class 的单个实例。因此,编译器完全跳过了从矩形和三角形到形状的构造函数调用。
检查此以了解更多详细信息: http://www.cprogramming.com/tutorial/virtual_inheritance.html https://isocpp.org/wiki/faq/multiple-inheritance