2013-03-29 6 views
0
class BaseClass { 
public: 
    BaseClass(const byte *buff, long size) { 
    // Some Computation 
    } 
}; 

class DerivedClass: public BaseClass { 
public: 
    std::vector<byte> filebuff; 
    long buff_size; 
    DerivedClass(): BaseClass(/*How should I send stuff here?*/) 
    { 
    } 
    /*return type??*/ cal_func(){ 
    // Some computation involving file descriptors. 
    // Store result in filebuff. Store size of filebuff in buff_size. 
    return /*what??*/; 
    } 
} 

Я могу думать только о следующем решении:C++: Как вызвать конструктор базового класса с несколькими аргументами?

DerivedClass(): BaseClass(&filebuff[0], cal_func) 

В приведенном выше случае, я сделаю функцию FUNC(), чтобы вернуть длину filebuff. Я полагаюсь на то, что filebuff - это только адрес, и, следовательно, не имеет значения, поставит ли компилятор вычисленное значение func в стек сначала или первый arg, filebuff.

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

+2

Нет, это неправильно: вы делаете '& filebuff [0]' перед 'filebuff'. – ildjarn

+0

Не могли бы вы объяснить, что было бы оптимальным способом передать адрес? –

+0

Редизайн вашего кода - рассмотрите возможность использования композиции, а не наследования. В коде нет ничего, что демонстрирует необходимость в производном классе. – ildjarn

ответ

2

Похоже, вы пытаетесь обернуть класс, который кто-то написал (например, в другой библиотеке), который принимает два аргумента, с другим классом (который вы написали), который имеет более чистый интерфейс. Я прав?

Ваше предлагаемое решение состоит в том, чтобы получить из другого базового класса, а затем использовать производный класс для хранения аргументов, которые помещаются в базовый класс. Проблема с вашим подходом выше заключается в том, что когда вы вызываете конструктор базового класса, производный класс еще не полностью сконструирован (т. Е. Файлбафф и bufsize не могут быть гарантированы инициализацией чего-либо).

Я предлагаю альтернативный подход, при котором вместо вывода, у вас есть WrapperClass, содержащий базовый класс, а также два элемента данных, у вас есть, например так:

class Wrapper { 
public: 
    Base base; 
    std::vector<byte> filebuff; 
    long buff_size; 
    Wrapper(); 
} 

Так в конструкторе класс-оболочка, вы можете сделать следующее:

WrapperClass::WrapperClass() { 
    //do whatever you want to initialize filebuff and buffsize here 
    calcfunc(); 

    //now pass them in to your base class 
    base = Base(filebuff, buffsize); 
} 

[Редактировать]

Alternative

Вышеупомянутое решение предполагает, что ваш базовый класс имеет конструктор по умолчанию, то есть Base(). Возможно, это не так, и вы не можете его создать. Если это так, то приведенный выше код не будет компилироваться, потому что нет способа инициализировать переменную-член base. Альтернативой является использование указателя на базовый класс, такой как Base*, или std::unique_ptr<Base>, или некоторый такой механизм вместо элемента Base напрямую. Таким образом, вы точно определяете, когда инициализируется базовый класс. Итак:

//class definition 
class Wrapper { 
public: 
    std::unique_ptr<Base> base; 
    std::vector<byte> filebuff; 
    long buff_size; 
    Wrapper(); 
} 

//... 

//constructor implementation 
WrapperClass::WrapperClass() { 
    //do whatever you want to initialize filebuff and buffsize here 
    calcfunc(); 

    //now pass them in to your base class 
    base = new Base(filebuff, buffsize); 
} 
+2

Почему 'Base *', а не 'Base'? Кстати, ваш код нарушает правило-три. – ildjarn

+0

Достаточно честный. Я просто пытался предложить альтернативу, используя композицию вместо наследования. Я буду редактировать базу. – maditya

+0

На самом деле, я просто понял, что зависит от того, имеет ли базовый класс конструктор по умолчанию, определенный для инициализации ... – maditya

2

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

class BaseClass { 
public: 
    BaseClass(const byte *buff, long size) { 
    // Some Computation 
    } 
}; 

class YourClass { 
public: 
    std::vector<byte> filebuff; 
    long buff_size; 
    BaseClass base; 

    DerivedClass() 
    : /* initialize filebuff and buff_size */, base(&filebuff[0], buff_size) {} 
}; 

Члены будут инициализированы в порядке их появления в определении класса, так что вы будете в состоянии передать filebuff и buff_size к базовый конструктор.

См. Также this answer на вопрос "C++: Инициализация заказа для классов участников".

+1

Единственное, что я действительно изменил, это полностью потерять размер файла и просто проставить размер вектора по мере необходимости, запустив базовый класс с помощью 'base (filebuff. data(), (long) filebuff.size()) ', но общая предпосылка хороша, если вы можете получить нужный буфер в списке инициализаторов. В целом, хороший подход. – WhozCraig

+0

@WhozCraig: Спасибо. – vitaut

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