2016-06-29 5 views
0

Возможно ли иметь другое определение типа, основанное на том, какой производный класс был создан?Могу ли я объявить о другом typedef в зависимости от класса?

Скажем, у меня есть родительский класс с виртуальной функцией func(), два члена Int и вектор типа myType и двух дочерних классов, которые разделяют те же ИНТ членов, и вектором, но их реализация func() требует myType к быть немного другим.

Например:

class Parent { 
    protected: 
    int myMember; 
    int myOtherMember; 
    std::vector<myType> vec; 

    public: 
    Parent(variable); 
    virtual int func() = 0; 
} 

class Child1 : public Parent { 
    private: 
    typedef <some type definiton> myType; 

    public: 
    Child1(variable) : Parent(variable){}; 
    int func() {return someFunc();}; 
} 

class Child2 : public Parent { 
    private: 
    typedef <some other type definiton> myType; 

    public: 
    Child2(variable) : Parent(variable){}; 
    int func() {return someOtherFunc();}; 
} 

Могу ли я сделать что-то вроде этого? когда я это пробовал, он создает циклическую зависимость в файлах заголовков, потому что класс Parent должен быть включен первым, но тогда ему необходимо определить myType.

Есть ли способ продвижения объявления myType в зависимости от класса? или мне просто нужно включить другой вектор myType в каждом классе, как так:

class Parent { 
    protected: 
    int myMember; 
    int myOtherMember; 

    public: 
    Parent(variable); 
    virtual int func() = 0; 
} 

class Child1 : public Parent { 
    private: 
    typedef <some type definiton> myType; 
    std::vector<myType> vec; 

    public: 
    Child1(variable) : Parent(variable){}; 
    int func() {return someFunc();}; 
} 

class Child2 : public Parent { 
    private: 
    typedef <some other type definiton> myType; 
    std::vector<myType> vec;  

    public: 
    Child2(variable) : Parent(variable){}; 
    int func() {return someOtherFunc();}; 
} 
+2

Сделать это аргументом шаблона вашего родительского класса. – tkausl

+0

ах, спасибо, я полностью забыл о шаблонах, это было пару лет с тех пор, как я сделал что-нибудь с C++, и я медленно вспоминаю все это. – guskenny83

ответ

3

Это работа для template мужчина!

Сначала мы объявляем Родитель

template <class TYPE> 
class Parent { 
    protected: 
    int myMember; 
    int myOtherMember; 
    std::vector<TYPE> vec; 

    public: 
    Parent(TYPE variable); 
    virtual int func() = 0; 
}; 

К сожалению, пользовательский тип, содержащийся в Child1 вне с этим подходом, поскольку тип должен быть объявлен прежде, чем мы можем специализировать шаблон на нем. Я использую int и double здесь для простоты. При необходимости замените.

using Child1Type = int; 
// or typedef int Child1Type; pre-C++11 
class Child1 : public Parent<Child1Type> { 
    public: 
    Child1(Child1Type variable) : Parent(variable){}; 
    int func() {return someFunc();}; 
}; 

using Child2Type = double; 
class Child2 : public Parent<Child2Type> { 

    public: 
    Child2(Child2Type variable) : Parent(variable){}; 
    int func() {return someOtherFunc();}; 
}; 

EDIT

Ударь себя за не получать это раньше (и сжигание слишком много времени, потому что я знал, что это было возможно, но мыслил в неправильном направлении)

Объявите тип в Родитель. Установите доступ на основе того, кто должен видеть этот тип. Здесь я сделал Type общественностью, чтобы проверить его в main. Тип объявляется в Parent и отображается (и через него public) Дети.

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

Я думаю, что это именно то, о чем упоминал Pixelchemist.

template <class TYPE> 
class Parent { 
    public: 
    using Type = TYPE; // declare Type here 
    protected: 
    int myMember; 
    int myOtherMember; 
    std::vector<Type> vec; // visible here 

    public: 
    Parent(Type variable); // here 
    virtual ~Parent(){} 
    virtual int func() = 0; 
}; 

class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced 
             // only once, here in the specialization 
    public: 
    Child1(Type variable) : Parent(variable){}; 
}; 

class Child2 : public Parent<uint32_t> { 

    public: 
    Child2(Type variable) : Parent(variable){}; 
}; 

int main() 
{ 
    // and visible way down here in main through Child1 and Child2 
    std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl; 
    std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl; 
} 

выход

Child 1: 2 
Child 2: 4 
+0

@ guskenny83, если вы видите это, я, наконец, понял, как сделать * точно, что вы были после. Я думаю. – user4581301

+0

Спасибо! это сработало! – guskenny83

+0

Последний вопрос, когда я возвращаю родительский конструктор к parent.cpp, я получаю 'parent.cpp: 6: 1: ошибка: недопустимое использование имени шаблона 'Parent' без списка аргументов Parent :: Parent (int variable) {', но когда я определяю точно такой же конструктор в файле заголовка, все в порядке. – guskenny83

0

Это то, что шаблоны для:

<template typename T> 
class Child : public Parent { 
private: 
    std::vector<T> vec; 
public: 
    Child(variable) : Parent(variable) {}; 
    int func() { return someOtherFunc(); }; 
} 

Тогда Child объявлен как что-то вроде:

Child<int> myChildInstance(10); 
+0

Я все еще немного смущен, когда идет мой typedef. Скажем, 'myType' довольно длинный и запутанный для каждого из Child1 и Child2? – guskenny83

+0

Я бы предпочел не иметь 'std :: vector vec' в классе Child, если это возможно, потому что в моем фактическом сценарии таких членов довольно много. – guskenny83

+0

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

1

Вы могли бы просто использовать шаблоны:

template<class T> 
struct Base 
{ 
    std::vector<T> v; 
}; 

struct D1 : public Base<int> 
{ 
    // all stuff in here comes into play when deriving from Base is already done 
    // Thus, compiler cannot know any typedefs from here inside Base... 
}; 

struct D2 : public Base<double> 
{ 
}; 

, где вы не можете использовать ЬурейеЕ из полученных в базовом классе. См. CRTP refer to typedef in derived class from base class.