Что скомпилировал MS Visual C++ 7?
От: McKolby  
Дата: 22.11.05 15:01
Оценка:
Хотелось бы узнать, почему не совпадает мнения у Visual C++ 7 с остальными компиляторами?
А именно, для MS Visual C++ 7 m_c->n::A::Number(); не эквивалентно ((n::A*)m_c)->Number(); в приведённом ниже примере. В результате выполнения строки кода m_c->n::A::Number(); вместо вызова виртуального метода родителя происходит вызов неизвестно чего. Зайдя в дебагере во внутрь этого вызова, видим что указател this смещён на 4 байта.
Избежать проблему можно несколькими способами, но хочу понять именно эту ситуацию.
Варианты правок, чтобы код работал правильно:
— Отказаться от namespace
— В классе I сделать функцию foo() невиртуальной
— При объявлении класса C поменять порядок родительских классов (класс I поставить последним)
— Заменить вызов m_c->n::A::Number(); на ((n::A*)m_c)->Number();
А чтобы вообще получить access violation нужно в исходном примере добавить в класс I член класса (например int i;).
Уважаемые, объясните пожалуйста, как Visual C++ понимает такой вызов? Что он пытается сделать?

#include <iostream>

using namespace std;

namespace n
{
    class A
    {
    public:
        void Number() const
        {
            A_Number();
        };
    private:
        virtual void A_Number() const = 0;
    };

    class B
    {
    public:
        void Number() const
        {
            B_Number();
        };
    private:
        virtual void B_Number() const = 0;
    };

}

class I
{
public:
    virtual void foo()
    {
    }
};


class C : public I, public n::A, public n::B
{
private:
    virtual void  A_Number() const 
    {
        cout << "C::A_Number";
    };
    virtual void B_Number() const 
    {
        cout << "C::B_Number";
    };
};

class D: public n::A, public n::B
{
public:
    D()
    {
        m_c = new C;
    };
    ~D()
    {
        delete m_c;
        m_c = NULL;
    };
private:
    C* m_c;
    virtual void A_Number() const
    {
        cout << "D::A_Number -> ";
        m_c->n::A::Number();          // only  ((n::A*)m_c)->Number();  work ok!
        cout << endl;
    }
    virtual void B_Number() const
    {
        cout << "D::B_Number -> ";
        m_c->n::B::Number();          // only  ((n::B*)m_c)->Number();  work ok!
        cout << endl;
    }
};

int main()
{
    D d;

    d.n::A::Number();
    d.n::B::Number();

    return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.