views:

129

answers:

6

I have two classes in C++, where one inherits from the other:

class A {
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       m_MyString = "New Value";
    }
}

Is there a difference between the above class B and this one?

class B : public A {
public: 
    void Initialize(){ 
       A::Initialize(); 
       A::m_MyString = "New Value";
    }
}

It seem using the scoping operator will result in a the string having garbage, correct? I'm thinking when it overrides, the A::m_MyString is different than B::m_MyString. Does this even make sense?

I'm seeing the variable get set in A, then when we return to B, have garbage. This has to do with "hidden" vs. overridden?

A: 

There is no difference between those two versions of class B. Is that the real code that you see garbage in?

Jim Buck
+1  A: 

Your code is not valid in many ways. It should look like:

class A { // << errors were here
public: 
    virtual void Initialize(){
        m_MyString = "Default value";
    }

protected: 
     string m_MyString;
}; // << lost ;

class B : public A // << errors were here
{
public: 
    virtual void Initialize(){  // << virtual
       A::Initialize(); // has no effect in the end

       A::m_MyString = "New Value"; // same as `m_MyString = "New Value";`
    }
}; // << lost ;

In the code above there is no difference with m_MyString. Post your actual code with error.

If your code looks like:

class B : public A
{
public: 
    virtual void Initialize(){
       // here is a difference
       A::m_MyString = "New Value"; 
       m_MyString = "New Value";
    }
protected: 
     string m_MyString; // !!! overridden
};

Then there is a difference because B has two instances of m_MyString: A::m_MyString and B::m_MyString.

Kirill V. Lyadvinsky
+1  A: 

Are you calling Initialize() from the constructor of A?

Calling virtual methods in constructors is not recommended. For example, if A's constructor looked like

A::A() {
  Initialize();
}

B's Initialize method would never get called.

Seeing your actual code would help a lot.

sdtom
A: 

The compiler should tell you if you're calling a virtual function from a constructor. But if not, that's definitely a problem.

I think you can make a virtual function final in the derived class, but maybe not. The variable should be the same, regardless of whether or not you explicitly define scope, unless you have a variable of the same name in the derived class.

mr_dude
In C++ a virtual function is virtual forever. There is no way to make it "final."
Zan Lynx
A: 

If this is how your code looks:

using namespace std;

class A 
{
    public:
        virtual void Initialize()
        {
            m_MyString = "Default value";
        }

    protected:
        string m_MyString;
};

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

        void display()
        {
            cout<<m_MyString<<endl;
        }
};

int main()
{
    B b;
    A a;

    b.Initialize();
    b.display();

    return 0;
}

Then there is no difference between the two versions of the class B that you described in your question. I added the display function just to make the values clear. By the definitions of the class that you have given, the m_MyString is not being overridden. So the m_MyString variable will have "New Value" assigned to it, i.e. both the classes A and B will share the variable m_MyString.

If you override the m_MyString in class B like

class B : public A 
{
    public:
        void Initialize()
        {
            A::Initialize();
            m_MyString = "New Value";
        }

    void display()
    {
        cout<<m_MyString<<endl;
    }

    protected:
        string m_MyString;
};

Then the value of B::m_MyString will contain "New Value" and the Value of A::m_MyString will contain "Default value".

Light_handle
A: 

It seem using the scoping operator will result in a the string having garbage, correct?

No, this should work and m_MyString will have "New Value" after b.Initialize() is called.

I'm thinking when it overrides, the A::m_MyString is different than B::m_MyString. Does this even make sense?

No, when a class B inherits another class A, the object of class B will have a union of the data members of the two. In this case, there is only one m_MyString that is A::m_MyString.

I'm seeing the variable get set in A, then when we return to B, have garbage. This has to do with "hidden" vs. overridden?

No, there is only one instance of m_MyString.

You definitely need to read this - http://www.openrce.org/articles/files/jangrayhood.pdf.

Sameer