#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 (каждый с независимыми параметрами и переменными). Я правильно понимаю этот код, это невозможно. Тем не менее, приятно знать.