2015-09-18 2 views
0

Я создал три класса: квадрат, прямоугольник и многоугольник. Квадрат наследуется от Rectangle, а Rectangle наследуется от Polygon.многоуровневое наследование без вызова конструктора суперкласса

Проблема в том, что всякий раз, когда я вызываю конструктор Square, конструктор Rectangle вызывается, и я получаю сообщение об ошибке. Как я могу это решить?

#include <iostream> 
using namespace std; 

// Multilevel Inheritance 

class Polygon 
{ 
protected: 
    int sides; 
}; 

class Rectangle: public Polygon 
{ 
protected: 
    int length, breadth; 
public: 
    Rectangle(int l, int b) 
    { 
     length = l; 
     breadth = b; 
     sides = 2; 
    } 
    void getDimensions() 
    { 
     cout << "Length = " << length << endl; 
     cout << "Breadth = " << breadth << endl; 
    } 

}; 

class Square: public Rectangle 
{ 
public: 
    Square(int side) 
    { 
     length = side; 
     breadth = length; 
     sides = 1; 
    } 
}; 

int main(void) 
{ 
    Square s(10); 
    s.getDimensions(); 
} 

Если я прокомментирую конструктор Rectangle, все будет хорошо. Но я хочу иметь оба конструктора. Я могу что-нибудь сделать?

+1

класс 'Площадь: общественное Rectangle' да ладно ... – SingerOfTheFall

+0

Вы не вызываете конструктор Rectangle непосредственно так конструктор по умолчанию будет называться ... Однако, это не имеет конструктора по умолчанию, вы должны определить его или напрямую вызвать свой. – Melkon

+0

Квадрат/прямоугольник фактически обсуждается в другом месте в качестве примера против наследования. Можно было бы искушать обратное отношение наследования, что также приводит к другим проблемам. Тем не менее, вызовите Rectangles ctor со стороной, стороной: 'Квадрат (int сторона): Прямоугольник (сторона, сторона) {...}' О, и у Петра есть точка в его ответе относительно квадрата. –

ответ

2

Вы не должны устанавливать элементы базового класса в конструктор производного класса. Вместо этого вызовите конструктор базового класса явно:

class Polygon 
{ 
protected: 
    int sides; 
public: 
    Polygon(int _sides): sides(_sides) {} // constructor initializer list! 
}; 

class Rectangle: public Polygon 
{ 
protected: 
    int length, breadth; 
public: 
    Rectangle(int l, int b) : 
     Polygon(2), // base class constructor 
     length(l), 
     breadth(b) 
    {} 
}; 

class Square: public Rectangle 
{ 
public: 
    Square(int side) : Rectangle(side, side) 
    { 
     // maybe you need to do this, but this is a sign of a bad design: 
     sides = 1; 
    } 
}; 
+0

Итак, следует ли использовать Polygon (1) в месте, где вы использовали «стороны = 1»? – Lokesh

+1

@Lokesh, no, вы можете назвать только конструктор базового класса _direct_, в данном случае, 'Rectangle'. Вы не можете вызвать конструктор 'Polygon' непосредственно из конструктора' Square'. Однако ваша обработка «сторон» пахнет мне как плохой дизайн: если ваш «Квадрат» является подклассом «Прямоугольник», то вы говорите, что «Квадрат» [является] (https://en.wikipedia.org/wiki/Is-a) 'Прямоугольник'. Таким образом, я ожидал бы, что большинство свойств, которые хранятся для 'Rectangle', также сохраняются для' Square'. Одним из таких свойств, по-видимому, является то, что «стороны == 2», поэтому я бы ожидал, что «Квадрат» будет иметь «стороны == 2». (продолжение) – Petr

+0

... На самом деле, определенно могут быть ситуации, когда ваши «Прямоугольник» и «Квадрат» будут иметь разные «стороны», но с учетом только кода, о котором идет речь, трудно предложить конкретное решение. Возможно, вы захотите задать для этого отдельный вопрос. Объясните, чего вы пытаетесь достичь, в частности (но не только!), Почему вам нужны разные «стороны» для «Прямоугольник» и «Квадрат», и, вероятно, вам будет лучше сказано. – Petr

2

конструктор должен быть

Square(int side) : Rectangle(side, side) { sides = 1; } 

в Rectangle не имеет конструктор по умолчанию.

+0

Я никогда не видел этот синтаксис. Что делает «:» здесь? – Lokesh

+1

Это список инициализаторов для членов класса. – Robinson

+0

Часто не имеет значения, инициализируйте ли вы этот элемент или явным назначением внутри кода ctor, хотя инициализация более чистая и потенциально более эффективная. Но именно в тех случаях, когда вы не можете по умолчанию инициализировать базовый класс (ваш случай) или членов - считайте ссылки! - вам нужна * инициализация. –

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