Проблема наследования C ++ - PullRequest
1 голос
/ 26 ноября 2010

У меня есть класс следующим образом:

Class A
{
   virtual int doSomethingCool() = 0;
};

Class B : public A
{
  int doSomethingCool();
};

Теперь проблема нравится, у меня есть набор классов, которые зависят от A как интерфейса. Мне нужно изменить прототип функции для одного из производных классов. то есть мне нужно передать ему параметр.

Class C: public A
{
 int doSomethingCool(int param);
};

Любые предложения, как я могу этого достичь?

Ответы [ 6 ]

2 голосов
/ 26 ноября 2010

Нет, вам не нужно добавлять его в базовый класс.

class A
{
public:
  virtual int doSomethingCool() = 0 {}
};

class B : public A
{
public:
  int doSomethingCool() {return 0;}
};

class C: public A
{
private:
  int doSomethingCool(); // hide base class version!
public:
  int doSomethingCool(int param) {return param;}
};

Вы все еще можете вызвать doSomethingCool(), если это сделано через указатель базового класса:

C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
1 голос
/ 26 ноября 2010

Добавьте его в интерфейс и по умолчанию вызовите существующий метод. Вам не нужно делать значение по умолчанию, но не делайте его чистым, иначе должны быть реализованы все производные классы Может быть, лучше оставить его неопределенным или бросить. Зависит от того, чего вы хотите достичь.

class A 
{ 
public:
   virtual int doSomethingCool() = 0; 
   virtual int doSomethingCool(int param) {doSomethingCool()}; 
};
0 голосов
/ 26 ноября 2010

Я бы представил другой, более конкретный интерфейс:

struct A
{
  virtual int doSomethingCool() = 0;
};

struct A_specific : A
{
  virtual int doSomethingCoolWithThis(int i) = 0;
};

class ConcreteA : public A
{
  int doSomethingCool() { return 0; }
};

class ConcreteA_specific : public A_specific
{
  int doSomethingCool() { return 0; }
  int doSomethingCoolWithThis(int param) { return param; }
};

Затем я запрограммировал бы на правильный интерфейс:

int main()
{
   const A& a1 = ConcreteA();
   const A_specific& a2 = ConcreteA_specific();

   a1.doSomethingCool();
   a2.doSomethingCool();
   a2.doSomethingCoolWithThis(2);
}

Просто чтобы дать вам другую идею ;-)

Удачи!

0 голосов
/ 26 ноября 2010

Это неправильно синтаксически C ++.

Нет, вы не можете изменить прототип.Как это будет использоваться?Каково будет значение параметра, если будет названа непараметрическая версия?

0 голосов
/ 26 ноября 2010

Нет проблем. Ты можешь это сделать. Единственное предостережение в том, что оно не будет рассматриваться как переопределение виртуальной функции базового класса.

class A 
{ 
public:
   virtual void doSomethingCool() = 0; 
};

class B : public A 
{
public:
   void doSomethingCool(); 
}; 

class C: Public A 
{ 
public:
   void doSomethingCool(int param); 
}; 


int main(){}

Так что, хотя это технически возможно, вы, возможно, захотите взглянуть на дизайн вашего интерфейса класса A.

Одним из вариантов может быть предоставление аргумента по умолчанию для A :: doSomethingCool

virtual void doSomethingCool(int = 0) = 0;
0 голосов
/ 26 ноября 2010

Сделайте функцию doSomethingCool() с параметром int в A.

class A
{
public:
    virtual void doSomethingCool(int param) = 0;
};
...