2011-12-16 2 views
0

Трудно объяснить, что именно я хочу здесь сделать, но у меня есть базовый класс и два класса, которые наследуют этот базовый класс. Оба класса, которые наследуют его, имеют свои собственные уникальные члены. Я хочу, чтобы иметь возможность передать оба метода, и определить этот метод, а затем получить доступ к их уникальным членам. Я не могу предположить, что будут только два класса, которые наследуют его, поэтому я ищу что-то более общее решение.как передать класс методу, и из базового класса обнаружить наследник?

Вот пример того, что я хотел бы сделать:

#include <iostream> 

class Base { 

    public: 
    int _type; 
    Base() { } 
}; 

class First : public Base { 
    public: 
    int _first_only; 

    First() { } 
}; 

class Second : public Base { 
    public: 
    int _second_only; 

    Second() { } 
}; 

void test (Base b) { 

    std::cout << "Type: " << b._type << std::endl; 

    if(b._type==1) { 
    std::cout << "First\n"; 
    // Want to be able to do this 
    std::cout << "Val: " << (First)b._first_only << std::endl; 
    } else if(b._type==2) { 
    std::cout << "Second\n"; 
    // And this 
    std::cout << "Val: " << (Second)b._second_only << std::endl; 
    } 
} 

int main() { 

    First f; 
    f._first_only=1; 
    f._type=1; 
    Second s; 
    s._type=2; 
    s._second_only=2; 

    test(f); 
    test(s); 
} 

ответ

1

Это похоже на другие ответы:

  1. Вы можете написать полиморфные классы, чтобы получить такое поведение с использованием виртуальных функций.
  2. Передайте объекты класса Dervied либо указателем, либо ссылкой, чтобы получить полиморфное поведение. В противном случае это приведет к разделению объектов. Функция test() приводит к обрезке объектов.

Этот код также может помочь вам. Вы можете видеть, что существуют разные способы печати типа. Я использовал GetBaseType(), GetDerivedType() и GetType(). Среди этих методов GetType() удобно для вас. Для удобства есть два конструктора. Конструкторы позволяют инициализировать элементы данных.

class Base { 
private: 
    int _type; 
public: 
    Base(int type) : _type(type) { } 
    int GetBaseType() { return _type; } 
    virtual int GetDerivedType() = 0; 
    virtual int GetType() { return _type; } 
}; 

class First : public Base { 
private: 
    int _first_only; 
public: 
    First() : Base(1), _first_only(1) { } 
    First(int first_only) : Base(first_only), _first_only(first_only) { } 
    int GetDerivedType() { return _first_only; } 
    virtual int GetType() { return _first_only; } 
}; 

class Second : public Base { 
private: 
    int _second_only; 
public: 
    Second() : Base(2), _second_only(2) { } 
    Second(int second_only) : Base(second_only), _second_only(second_only) { } 
    int GetDerivedType() { return _second_only; } 
    virtual int GetType() { return _second_only; } 
}; 

void test (Base &b) { 
    std::cout << "Type: " << b.GetBaseType() << std::endl; 
    std::cout << "Type: " << b.Base::GetType() << std::endl; 

    std::cout << "Dervied type: \n"; 
    std::cout << "Val: " << b.GetDerivedType() << std::endl; 
    std::cout << "Val: " << b.GetType() << std::endl; 
} 

int main() { 

    First f(1); 
    Second s(2); 

    test(f); 
    test(s); 

    First f1; 
    Second s1; 

    test(f1); 
    test(s1); 
} 
1
  1. Либо объявить virtual функцию в Base
  2. Перемещение общих типов членов из First и Second в Base.

Для вашей конкретной проблемы, второй вариант лучше:

class Base { 
    public: 
    int _member; // have getter() method, if '_member' is private 
    Base() { } 
}; 

Внутри test():

void test (Base &b) { // <--- practice to pass by reference if copy is not needed 
    // use b._member; 
}; 
1

Ваш код не работает полиморфно, потому что вы передаете функцию-параметр, значение, которое приводит к нарезке.

Если у вас есть метод, который делает разные вещи для разных типов, рассмотрите возможность перегрузки его для каждого из этих типов.

0

Три вещи, которые я хотел бы сделать:

  • В общем переключения на коды типа не считается хорошим объектно-ориентированный дизайн: Вместо того, чтобы тянуть коммутируемого код в классы.
  • Я также установил теги типа в конструкторе конкретных классов.
  • И, как уже упоминалось, вам необходимо передать аргумент по ссылке, чтобы избежать нарезки.

Вот что код будет выглядеть следующим образом:

#include <iostream> 

class Base { 

    public: 
    int _type; 
    Base() { } 
    virtual void print_to_stream(std::ostream & os) const =0; 
}; 

class First : public Base { 
    public: 
    int _first_only; 

    First() { _type =1; } 
    void print_to_stream(std::ostream & os) const 
    { 
     os<<"First\n"; 
     os<<"Val: " << _first_only << std::endl; 
    } 
}; 

class Second : public Base { 
    public: 
    int _second_only; 

    Second() { _type=2; } 

    void print_to_stream(std::ostream & os) const 
    { 
     os << "Second\n"; 
     os << "Val: " << _second_only << std::endl; 
    } 
}; 

void test (Base & b) 
{ 
    std::cout << "Type: " << b._type << std::endl; 
    b.print_to_stream(std::cout); 
} 

int main() { 
    First f; 
    f._first_only=1; 
    Second s; 
    s._second_only=2; 

    test(f); 
    test(s); 
}