Вызов не виртуальной функции базового класса, которая была переопределена? - PullRequest
0 голосов
/ 03 ноября 2010

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

Что я хочу, это (о, а это C ++):

class A {
 public:
 void f() { doSomethingA(); }
};
class B : public A {
 public:
 void f() { A::f(); doSomethingB(); }
};

Однако, когда я делаю это, A::f вызывается с this == 0, что, очевидно, приводит к segfault. Я что-то не так делаю, или это просто невозможно? Моя текущая опция - прибегнуть к статическим функциям и явно передать объект, но я бы предпочел это так.

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

Любая помощь приветствуется

EDIT
Спасибо всем за ответы, похоже, я наткнулся на ошибку в моей среде сборки, минимальный тестовый пример прошел нормально; и то же самое произошло с оптимизацией. Думаю, я мог бы попробовать это, прежде чем задавать вопрос, но обычно я предполагаю, что я делаю что-то не так.

Больше нечего здесь видеть, двигайтесь вперед .. Приносим извинения за неудобства ...:)

Ответы [ 5 ]

1 голос
/ 03 ноября 2010

Попробуйте

static_cast<A*>(this)->f()

Должно работать.

РЕДАКТИРОВАТЬ:

Если это не так, сначала проверьте this в B::f().

1 голос
/ 03 ноября 2010

Предполагая, что B не наследуя от A, является опечаткой (иначе я не вижу этой компиляции), похоже, указатель B, для которого вы первоначально вызываете f, является нулевым. Проверьте исходный пункт вызова, потому что (при условии опечатки) то, что вы написали, должно работать.

1 голос
/ 03 ноября 2010

Ваш код не очень хорошо вписывается в текст.В тексте вы говорите о наследовании, но код не показывает ничего (и, по крайней мере, как есть, он даже не должен компилироваться).

Если вы используете наследование:

class A { 
public:
    void f() { doSomethingA(); }
};

class B : public A { 
public:
    void f() { A::f(); doSomethingB(); }
};

Тогда, когда вы вызываете A::f(), this определенно должен не быть указателем NULL - это должен быть действительный указатель на "1010 *" подобъект "в объекте B(до тех пор, пока вы используете одиночное наследование, в большинстве компиляторов это будет адрес объекта, для которого вы вызывали B::f(), просто приведение от B * const к A * const).

0 голосов
/ 03 ноября 2010

Игнорируя «правильность» этого, нет ничего плохого в том, что вы описываете.Я предполагаю, что ваш пример кода будет больше похож на следующий, хотя на самом деле у вас есть наследование, которое вы описываете:

struct A {
 void f() { cout << "hi" << endl; }
};
struct B : public A {
 void f() { A::f(); }
};
0 голосов
/ 03 ноября 2010

Вы не указали, что B наследует от A:

class B : public A {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...