2013-02-24 4 views
0

Я хочу создать 2 вида классов. классы будут иметь аналогичную функцию «set», но набор funct получит «int» в классе B и double в классе C. (A - абстрактные calss, но это не требуется). Что мне нужно сделать?классы в C++ и виртуальные функции

class A{ 
    int x; 
public: 
    A (int t=1): x(t){} 
    virtual void set()=0; 
} 

class B: public A{ 
    int y; 
public: 
    virtual void set (int y); 
}; 

class C: public A{ 
    double y; 
public: 
    virtual void set (double y); 
}; 

void main() 
{ 
    B b; //error 
    C c; //error 
} 
+3

Создайте два отдельных класса без наследования? – juanchopanza

+0

с наследованием. двумя баллонами являются B и C. – YkI

+2

Было бы более целесообразно использовать шаблоны для этого, чем наследование – Chad

ответ

2

Создание единого шаблонного класса и экземпляра, который когда-либо вам нужно в то время, или ЬурейеЕ B и C из класса шаблона:

template< typename T > class A 
{ 
public:    A() : mValue() {} 

      void Set(T value) { mValue = value; } 

private: T  mValue; 
}; 

typedef A<int> B; 
typedef A<double> C; 
+0

хорошая идея! спасибо !!! – YkI

+0

Это неплохая идея, но она решает совершенно другую проблему, чем вы просили. Таким образом, вы либо не понимаете разницы, либо не понимаете, что вы просили. – Slava

+0

@ Слав Хорошо, я признаю, что пропустил исходное содержание A, но их можно легко добавить обратно в шаблон. Весь вопрос был задан, как иметь два класса, которые выглядят похожими, но работают с разными типами данных - для них созданы точные шаблоны проблемных доменов. – 2013-02-24 20:09:56

0

Трюк состоит в том, чтобы найти общие части B и C и поместить их в базовый класс. Материал, который отличается должен перейти в конструктор параметр производного класса:

class A { 
    virtual std::string get() const=0; 
    virtual void set(std::string s)=0; 
}; 
class B : public A { B(int a) : a(a) { } int a; }; 
class C : public A { C(float b) : b(b) { } float b; } 

Для реализации функций, вам необходимо следующее:

void B::set(std::string s) { 
    stringstream ss(s); 
    ss >> a; 
} 
void C::set(std::string s) { 
    stringstream ss(s); 
    ss >> b; 
} 

функции выглядят одинаково, но на самом деле вызов другого оператора >>.

+0

B и C имеют одинаковые «int x» и различные переменные «float c» и «int a». также я хочу, чтобы B и C использовали одну и ту же функцию имени «set», которая что-то делала ... – YkI

+0

ykl: вам понадобится преобразование из std :: string в int/float для реализации функций get/set() в этом версия. – tp1

+0

я думаю, что я не понял ... – YkI

1

Есть довольно много вариантов, чтобы решить эту проблему, но в первую очередь, виртуальная функция должна иметь одну и ту же подпись (может быть исключение, но это не имеет отношения к вашему делу). Поэтому решение состоит в том, чтобы иметь и аргументы (аргументы), которые разрешат все случаи. Есть варианты:

Проходят все варианты к функции, и использовать только частности один:

class A { 
public: 
    virtual void set(int, double) = 0; 
}; 
class B { 
    int y; 
public: 
    virtual void set(int val, double) { y = val; } 
}; 
class C { 
    double y; 
public: 
    virtual void set(int , double val) { y = val; } 
}; 

Это не очень хорошее решение, и не очень хорошо масштабируется, поэтому мы можем использовать союз:

Union Arg { 
    int i; 
    double d; 
}; 

class A { 
public: 
    virtual void set(Arg a) = 0; 
}; 
// derived classes are trivial, so omitted 

Союз не типобезопасен, поэтому мы можем использовать повышение :: вариант вместо

другое решение, чтобы иметь другую иерархию для параметра:

struct Arg { 
    virtual ~Arg(); 
}; 
struct IntArg : Arg { 
    int m_value; 
}; 
struct DoubleArg : Arg { 
    double m_value; 
}; 
class A { 
    virtual void set(const Arg &a) = 0; 
}; 
class B { 
    int y; 
public: 
    virtual void set(const Arg &a) { y = dynamic_cast<const IntArg &>(a).m_value; } 
}; 
class C { 
    double y; 
public: 
    virtual void set(const Arg &a) { y = dynamic_cast<const DoubleArg &>(a).m_value; } 
}; 

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

Это только некоторые варианты, их может быть гораздо больше, что подходит вам лучше всего, вы можете решить только на основе ваших требований к программе.

1

Ditch наследование и виртуальная вещь. Вы не можете легко получить результат статически неизвестного типа с помощью виртуальной функции. Итак:

class A 
{ 
private: 
    int x_; 
public: 
    A(int const t = 1): x_(t) {} 
}; 

class B 
    : public A 
{ 
private: 
    int y_; 
public: 
    void set(int const y); 
}; 

class C 
    : public A 
{ 
private: 
    double y_; 
public: 
    void set(double const y); 
}; 

int main() 
{ 
    B b; // OK 
    C c; // OK 
} 

Обратите внимание на точку с запятой в конце класса A и int main вместо void main.

Такие детали имеют значение.

В противном случае вы можете отправить людей, которые хотят вам помочь, на долгие дикие гусиные погони. И ты этого не хочешь, не так ли? Поэтому убедитесь, что код, который вы публикуете, был принят компилятором, за исключением, возможно, для неприятных частей, которые вы хотите показать, не компилируется.

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