Вызов функции класса из дочернего класса

#c #class

#c #класс

Вопрос:

Предположим, что объект класса B является членом класса A.

 class B{
    //Definitions
}

class A{
public:
    A();
    B b_child;
    int some_function();
}
  

Одна из функций, определенных внутри B , должна вызывать (общедоступную) функцию от ее владельца (родительского?) A . Есть ли непосредственный способ сделать это?

Единственный способ, которым мне пока удалось это сделать, — реализовать его вне определений классов:

 A a_obj;
a_obj.b_child.setowner(amp;aobj);
  

который сообщает b_child , кто является его владельцем. Мне это не нравится. Я бы предпочел использовать какой-нибудь встроенный метод для b_child доступа к его родительскому классу (если это возможно). Если это невозможно, я бы предпочел передать адрес владельца непосредственно в конструкторе for B , но я не знаю, как ссылаться A на адрес внутри его определения.

Комментарии:

1. Это хороший вопрос, хотя вы должны знать, что «дочерний класс» имеет очень специфическое значение в C , связанное с наследованием.

Ответ №1:

Не существует встроенного метода для получения «владельца» переменной, что бы это ни значило. Ваш подход к настройке владельца правильный. Кроме того, выполнение этого при построении B также является правильным решением. Пример кода:

 class B
{
public:
    explicit B( A* owner ) : _owner( owner ) {}

    ...
private:
    A* _owner;
};

class A
{
public:
    A() : _child( this ) {}

    ...
private:
    B _child;
};
  

Обратите внимание, что некоторые компиляторы могут выдавать вам предупреждение за использование this в этом контексте, но это нормально для текущего примера. Просто убедитесь, что вы не вызываете какие A -либо функции-члены из B конструктора, поскольку полученный вами указатель все еще указывает на неконструированный объект на этом этапе.

Ответ №2:

Я бы предпочел использовать какой-нибудь встроенный метод для b_child для доступа к его родительскому классу (если это возможно).

Нет, это не так.

но я не знаю, как ссылаться на адрес A внутри его определения.

Вы можете использовать this указатель.

 A() : b_child(this) { }
  

Ответ №3:

Вы должны использовать this указатель для ссылки на объект внутри него

 class B{
    //Definitions
}

class A{
private:
    B b_child;
public:
    A()
    { 
       b_child.set_owner(this);
    }
}
  

Ответ №4:

Вы должны определить B следующим образом:

 template <class T, int N>
class B
{
public:
  int example_func() { return static_cast<Tamp;>(*this).some_function(); }
};
  

А затем создайте B<A> подкласс A (чтобы он мог вызывать A напрямую).

 class A : protected B<A,0>, protected B<A,1>
{
    A();
    int some_function() { return 42; }
};
  

Это называется любопытно повторяющимся шаблоном шаблона.

Если вы не хотите B быть шаблонным классом и собираетесь использовать только B with A , тогда подойдет следующее:

 template <int N>
class B
{
public:
  int example_func() { return static_cast<Aamp;>(*this).some_function(); }
};

class A : protected B<0>, protected B<1>
{
    A();
    int some_function() { return 42; }
};
  

В качестве альтернативы, если вы хотите использовать B with не только A , но не хотите создавать B шаблонный класс (скажем, если вам нужна коллекция указателей на B ), вы можете сделать следующее:

 template <int N>
class B
{
public:
  int example_func() { return some_function(); }
  virtual int some_function() = 0;
};

class A : protected B<0>, protected B<1>
{
    A();
    int some_function() { return 42; }
};
  

Это разрешит some_function() вызов во время выполнения и потребует сохранения виртуального указателя в вашем классе.

Комментарии:

1. Есть ли преимущество по сравнению с методом в других ответах?

2. Вы сохраняете указатель, поскольку нет необходимости хранить указатель на A в B, поскольку B является частью A (и, следовательно, имеет тот же адрес).

3. Хорошо, это заняло у меня некоторое время, но я думаю, что я не могу использовать эти параметры. Хотя я не указывал в вопросе, мне нужно, чтобы A содержал несколько объектов класса B (каждый с независимыми параметрами и переменными). Я правильно понимаю этот код, это невозможно. Тем не менее, приятно знать.