Передача аргументов в конструктор Base с использованием переменных-членов производного класса в C / C ++ - PullRequest
0 голосов
/ 25 марта 2020

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

Я подумал, что при создании этой архитектуры я буду использовать базовый класс, содержащий все необходимые методы, и производные классы (DerivedV1, DerivedV2 и др.). c) где я бы просто определил эти жестко закодированные параметры как переменные-члены, а затем передал их в качестве параметров конструкции в базовый класс.

Вот минимальный пример кода: (он развернут на микроконтроллере, поэтому использование массивов вместо векторов также не учитывает использование std :: cout, он был включен только здесь, чтобы проиллюстрировать проблему )

#include <iostream>
using namespace std;

void print_array(uint16_t *array, uint16_t size){
    cout<<"[ ";
    for(int i=0; i < size-1; i++){
      cout<<array[i]<<", ";
    }
    cout<<array[size-1]<<" ]"<<endl;
}


class BaseClass{
protected:
  std::string id_;
  uint16_t num_cats_;    
  uint16_t num_dogs_;     
  uint16_t *cat_mapping_;
  uint16_t *dog_mapping_; 
  uint16_t combinations_;

public:  
    BaseClass(string id, uint16_t num_cats, uint16_t num_dogs,
            uint16_t *cat_map, uint16_t *dog_map){

        cout<<"Base Constructor"<<endl;
        id_ = id;
        num_cats_ = num_cats;
        num_dogs_ = num_dogs;
        cat_mapping_ = cat_map;
        dog_mapping_ = dog_map;
        combinations_ = num_cats_*num_dogs_;
        cout<<"Num cats: "<<num_cats_<<endl;
        cout<<"Num dogs: "<<num_cats_<<endl;
        print_array(cat_mapping_, num_cats_);
        print_array(dog_mapping_, num_dogs_);
        cout<<"Combinations: "<<combinations_<<endl;
    }

    virtual ~BaseClass(){};

};


class DerivedClassV1 : public BaseClass 
{
private:
  uint16_t num_cats_ = 10;
  uint16_t cat_map_[10] = {31, 15, 20, 32, 13, 25, 19, 16, 28, 23};
  uint16_t num_dogs_ = 8;
  uint16_t dog_map_[8] = {5, 25, 23, 4, 13, 15, 14, 26};

public:
  DerivedClassV1(string id) : BaseClass(id, num_cats_, num_dogs_, cat_map_, dog_map_){
    cout<<"Derived Constructor";
  }
};


int main()
{
    DerivedClassV1 dummy("v1");
    return 0;
}

Выполнение этого кода приводит к выводу мусора:

Базовый конструктор
Количество кошек: 64
Количество собак: 64
[0 , 0, 2, 0, 0, 0, 4781, 64, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 4704, 64, 0, 0, 3040, 64, 0, 0 , 42640, 13254, 32766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44869, 10268, 32576, 0, 0, 0, 0, 0, 42648, 13254, 32766, 0, 0 , 0, 1, 0, 3456, 64, 0, 0, 0, 0, 0, 0, 13708, 48499]
[0, 0, 0, 0, 0, 0, 4704, 64, 0 , 0, 3040, 64, 0, 0, 42640, 13254, 32766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44869, 10268, 32576, 0, 0, 0, 0, 0 , 42648, 13254, 32766, 0, 0, 0, 1, 0, 3456, 64, 0, 0, 0, 0, 0, 0, 13708, 48499, 5513, 17381, 3040, 64, 0, 0, 42640 , 13254, 32766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13708, 63219, 29188, 48153, 13708, 57481, 17840, 484 85, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4704, 64, 0, 0, 42648, 13254, 32766, 0, 1, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 3040, 64, 0, 0, 42640, 13254, 32766, 0, 0, 0, 0, 0, 3081]
Комбинации: 7936
Производный конструктор

Что я здесь не так делаю? Почему аргументы, отправляемые в BaseClass, не являются правильными, определенными в производном классе?

Должен ли я делать это по-другому? Любая помощь приветствуется

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

Поведение вашей программы не определено.

Концептуально, DerivedClassV1::cat_map_ & c. не существует в точке, где создается базовый класс.

Указатель на такой массив (например, cat_map в конструкторе базового класса) фактически свисает.

Не можете использовать полиморфизм для получения соответствующих массивов?

0 голосов
/ 25 марта 2020

Вы можете передать значения DerivedClassV1 в BaseClass с помощью шаблона. Но значения должны быть постоянными c, чтобы они инициализировались перед базовым классом.

#include <iostream>
using namespace std;

void print_array(const uint16_t *array, uint16_t size){
    cout<<"[ ";
    for(int i=0; i < size-1; i++){
      cout<<array[i]<<", ";
    }
    cout<<array[size-1]<<" ]"<<endl;
}


template <class T>
class BaseClass {
protected:
  std::string id_;
  const uint16_t *cat_mapping_ = T::cat_map_;
  const uint16_t *dog_mapping_ = T::dog_map_; 
  uint16_t combinations_;

public:  
    BaseClass(string id){

        cout<<"Base Constructor"<<endl;
        id_ = id;
        combinations_ = T::num_cats_*T::num_dogs_;
        cout<<"Num cats: "<<T::num_cats_<<endl;
        cout<<"Num dogs: "<<T::num_dogs_<<endl;
        print_array(cat_mapping_, T::num_cats_);
        print_array(dog_mapping_, T::num_dogs_);
        cout<<"Combinations: "<<combinations_<<endl;
    }

    virtual ~BaseClass(){};
};


class DerivedClassV1 : public BaseClass<DerivedClassV1> 
{
public:
  static const uint16_t num_cats_ = 10;
  static constexpr uint16_t cat_map_[10] = {31, 15, 20, 32, 13, 25, 19, 16, 28, 23};
  static const uint16_t num_dogs_ = 8;
  static constexpr uint16_t dog_map_[8] = {5, 25, 23, 4, 13, 15, 14, 26};

public:
  DerivedClassV1(string id) : BaseClass(id){
    cout<<"Derived Constructor";
  }
};
constexpr uint16_t DerivedClassV1::cat_map_[10];
constexpr uint16_t DerivedClassV1::dog_map_[8];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...