2013-11-29 2 views
0

Были попытки улучшить понимание виртуальных функций. Ради аргумента, скажем, у меня есть базовый класс:C++ Функции, вызывающие виртуальные функции внутри

class Shape 
{ 
protected: 
    string _name; 
    int _num; 
public: 
    Shape(); 
    virtual double CalcShape(); 
}; 

и 2 нижних классов:

class Rectangle : public Shape 
{ 
private: 
    double _height; 
    double _width; 
public: 
    Rectangle(); 
    Rectangle(double, double); 
    double GetHeight(); 
    double GetWidth(); 
    double CalcShape(double, double); //calculates rectangle 
}; 

class Triangle : public Shape 
{ 
private: 
    double _side1; 
    double _side2; 
    double _side3; 
public: 
    Triangle(); 
    Triangle(double, double, double); 
    double GetSide(); 
    double CalcShape(double, double, double); //calculates triangle 
}; 

Say У меня также есть функция под названием ShowCalc(Shape&);. Эта функция вызывает функцию CalcShape().

void ShowCalc(Shape& sh) 
{ 
    return sh.CalcShape(); 
} 

Теперь есть способ получить эту функцию CalcShape() принимать ввод GetSide() функции Оба треугольника и прямоугольника GetHeight() и GetWidth() видя, как треугольник принимает 3 параметра и Прямоугольник занимает 2?

+1

Просто избавиться от параметров. 'CalcShape' им не нужны, они уже являются переменными-членами. –

+0

@PeterWood: если эта функция действительно является сеттером ('CalcShape (2,4)' может означать в каком-то странном дизайне: 'setWidthHeight (2,4)') –

ответ

2

Я вижу несколько ошибок при проектировании здесь:

  • вы не можете использовать virtual метод со ссылками: ссылка указывает на реальный объект этого указанного типа. Динамическая отправка не работает, потому что Shape& - это Shape, и даже если для инициализации значения присваивается ему класс children, все, что является производным, отбрасывается из-за object slicing.
  • virtual функции предназначены для использования, когда переопределенные методы в подклассах имеют конкретную реализацию. Переопределенный метод имеет ту же подпись исходного метода. В вашем случае у вас есть CalcShape(void) в Shape и CalcShape(double, double) в Rectangle. Это не переопределение, это перегрузка, что является совершенно другой вещью. Вы можете взять ключевое слово override в C++ 11, чтобы убедиться, что вы правильно переопределяете виртуальные методы.
  • virtual методы должны быть чистыми, если реализация на базовом классе не имеет смысла (поскольку вы не можете вычислить область неизвестной формы типа). Если бы у вас был этот чистый (= 0), компилятор предупредил бы вас о том, что ни один из классов детей на самом деле не отменяет его.

Чтобы получить то, что вы хотите, вы должны использовать переменные-члены в реализации, не передавать их через вызов, например:

class Shape { 
    virtual double calcArea() = 0; 
} 

class Rectangle : public Shape { 
    private: 
    double width, height; 
    public: 
    virtual double calcArea() override { return width*height; } 
} 

Shape *shape = new Rectangle(10,20); 
double area = shape->calcArea(); 
+0

А, так, если бы я хотел переопределить метод в дочернем класса, они должны иметь одинаковые параметры? Мне нравится это ключевое слово переопределения в этом случае. – xavi

+0

Дело в том, что это переопределение, когда оно заменяет реализацию класса предков. Чтобы заменить его, он должен иметь одно и то же имя и те же аргументы. http://en.wikipedia.org/wiki/Method_overriding. На странице wikipedia есть пример в C++, который также похож на ваш. – Jack

Смежные вопросы