Определение, переопределяет ли производный класс метод из базового класса - PullRequest
10 голосов
/ 29 декабря 2010
class B {
virtual int foo();
};

class D : public B {
virtual int foo() { cout<<"D\n"; }
};

int B::foo()
{
   /* how do i tell if this->foo() is overridden by a subclass, or if it will */
   /* simply recurse into B::foo()? */
   this->foo();
}

main()
{
D d;
d.B::foo();
}

Ответы [ 5 ]

8 голосов
/ 29 декабря 2010

Ответ: вы не можете.

Я бы расширился, если бы было что расширить.

2 голосов
/ 29 декабря 2010

Один из подходов состоит в том, чтобы foo() чисто виртуальная функция в B, и также определяла ее.Таким образом вы убедитесь, что производные классы B должны определять foo().Вот B,

class B
{
public:
        virtual int foo() = 0; //pure virtual function
};

//pure virtual function also has a default implementation!
int B::foo()
{
        std::cout << "B" << std::endl;  
        this->foo(); //this will call the overridden foo() in the derived class!
        return 0;
}

Если производный класс B не реализует foo (), то вы даже не можете создать экземпляр такого производного класса!

См. Полный рабочий код наideone: http://www.ideone.com/m8O2s

Кстати, мое личное мнение таково, что такой дизайн классов плох для начала.Что если вы позвоните B::foo() из производного класса foo ()?Рекурсивный

1 голос
/ 29 декабря 2010

Я ненавижу даже предоставлять это .. но вот оно

int B::foo()
{
std::cout << "B" << std::endl;  
if (typeid (*this) != typeid(B))
    this->foo();
return 0;
}

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

Я хочу доказать, что он работает в MSVC ++ 2010.

#include "stdafx.h"
#include <iostream>

class B {
public:
virtual int foo();
};

class D : public B {
public:
virtual int foo() {
    std::cout<<"D\n"; return 0; 
}
};

int B::foo()
{
std::cout << "B" << std::endl;  

/* how do i tell if this->foo() is overridden by a subclass, or if it will */
/* simply recurse into B::foo()? */
if (typeid (*this) != typeid(B))
    this->foo();

return 0;
}


int main(int argc, _TCHAR* argv[])
{
D d;
d.B::foo();

B b;
b.foo();
return 0;
}

Выход

B
D
B

Доказательство того, что это не всегда будет работать

Измените D на это, и оно больше не будет работать

class D : public B { };
0 голосов
/ 29 декабря 2010

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

0 голосов
/ 29 декабря 2010

Самый безопасный способ - вообще не переопределять foo (), но разрешать переопределение функции OnFoo (), которая вызывается из базового класса, если вы не можете доверять своим программистам.MFC многое делает для обеспечения поведения по умолчанию (а не для защиты от повторной проверки).

Затем, на статическом уровне, все, что реализует OnFoo (), легко обнаруживается с помощью «Найти в файлах».

Например (не проверено на синтаксис / компиляцию и не поточно-ориентировано)

class B
{
public:
    B()
    {
        m_bInFoo=false;
    } 

    int foo()
    {
        if( !m_bInFoo )
        {
            m_bInFoo=true;

            int nRet = OnFoo();

            m_bInFoo=false;

            return nRet;
        }

        return 0;// probably throw exception
    }

protected:
    // inherited classes override OnFoo(), and never call OnFoo();
    virtual int OnFoo(){ return 0 };

private:
    bool m_bInFoo;
}
...