Thread: Trying to break inheritance

  1. #1
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594

    Trying to break inheritance

    I wanted to make sure I still remembered all the ins and outs of inheritance, so I tried to break my compiler doing some wacky things with it.

    I found that MSVC will not notice a protected constructor if you have the function body in the header. Put it in a .cpp, you're fine. MSVC sometimes doesn't notice you've made a change to implimentation in a header file, and requires you to clean and rebuild in order to have the change have any effect. This was not the case in this scenario.

    I also found this weird break: if you declare a constructor or an assigment operator as protected, it won't let derived classes use them.

    BaseProtected.h
    Code:
    class BaseProtected
    {
    	protected:
    		BaseProtected();
    		const BaseProtected & operator = (const BaseProtected & b);
    
    		int prot;
    };
    BaseProtected.cpp
    Code:
    #include "BaseProtected.h"
    BaseProtected::BaseProtected() 
    : prot(1)
    {}
    
    const BaseProtected & BaseProtected::operator = (const BaseProtected & b)
    { 
    	prot = b.prot; 
    	return *this;
    }
    DerivedProtected.h
    Code:
    #include "BaseProtected.h"
    class DerivedProtected : public BaseProtected
    {
    	public:
    		DerivedProtected();
    		void DoStuff();
    
    		int newGuy;
    };
    DerivedProtected.cpp
    Code:
    #include "DerivedProtected.h"
    DerivedProtected::DerivedProtected()
    :newGuy(99)
    {}
    
    void DerivedProtected::DoStuff()
    {
    	BaseProtected a, b; //MSVC error C2248
    	a = b;//MSVC error C2248
    }
    I find that interesting. If you were to try and mess with the prot member after a and d are declared, it also issues errors saying you can't access protected memebers. As far as I know, this is not exptected behavior.

    If anybody else would like to mess around with this in MSVC or any other compiler, please let me know what results you get.
    If you'd like to enlighten me, I'm up for that, too.
    Last edited by skorman00; 11-02-2005 at 10:12 PM.

  2. #2
    Registered User
    Join Date
    Sep 2004
    Posts
    197
    mm, doesn't DerivedProtected.h need to include BaseProtected.h ?

    Made that quick edit to include it, and tried to complie it with GCC 3.3.6, here is the error output

    Code:
    BaseProtected.h: In member function `void DerivedProtected::DoStuff()':
    BaseProtected.h:4: error: `BaseProtected::BaseProtected()' is protected
    DerivedProtected.cpp:8: error: within this context
    BaseProtected.h:4: error: `BaseProtected::BaseProtected()' is protected
    DerivedProtected.cpp:8: error: within this context
    BaseProtected.h:5: error: `const BaseProtected& BaseProtected::operator=(const
       BaseProtected&)' is protected
    DerivedProtected.cpp:9: error: within this context
    I can't off hand remeber what my book says about protected members (been doing too much with Ada as of late)
    Last edited by Xipher; 11-02-2005 at 10:16 PM.
    If any part of my post is incorrect, please correct me.

    This post is not guarantied to be correct, and is not to be taken as a matter of fact, but of opinion or a guess, unless otherwise noted.

  3. #3
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    It does, copy and paste error. Editing.

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    A non-constructor function that is protected in the base class can be called from your doStuff() function in the derived class. So, that indicates to me that constructors aren't inherited.
    Last edited by 7stud; 11-02-2005 at 11:30 PM.

  5. #5
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    Constructors are not inherited. It doesn't make sense to inherit a constructor. However, I should be able to create an instance of a parent class, since I have access to protected members. Also, as stated above, if you try to instantiate a class of the parent, you get an error stating that you cannot access that protected constructor, and ALL other references to protected members or methods will issue that error as well.

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Constructors are not inherited. It doesn't make sense to inherit a constructor.
    Why not? In fact, you're lamenting the lack of that very behavior. In addition, I think there's a proposal to change that in the C++ language.

    Also, as stated above, if you try to instantiate a class of the parent, you get an error stating that you cannot access that protected constructor
    The "protected" access specifier means that that the member is private, but that it can be inherited by derived classes. So, if the method isn't inherited, why should a private member in another class be accessable?

    if you try to instantiate a class of the parent, you get an error stating that you cannot access that protected constructor, and ALL other references to protected members or methods will issue that error as well.
    I can't agree with the second part, at least for VC++6.0:
    Code:
    #include <iostream>
    using namespace std;
    
    class BaseProtected
    {
    	protected:
    		BaseProtected() : prot(1)
    		{
    		}
    
    		void someFunc()
    		{
    			cout<<"protected base function"<<endl;
    		}
    
    		int prot;
    };
    
    class DerivedProtected : public BaseProtected
    {
    	public:
    		int newGuy;
    
    		DerivedProtected() : newGuy(99)
    		{
    		}
    
    		void DoStuff()
    		{
    			//BaseProtected a; error
    
    			someFunc();
    		}
    };
    
    
    int main()
    {
    
    	DerivedProtected a;
    	a.DoStuff();  //output: "protected base function"
    	
    	return 0;
    }
    It's plain that constructors don't obey the normal rules of inheritance, so maybe the rule is that a protected constructor can only be accessed in the initializer list of a derived class constructor, and therefore a "protected" constructor does not give class wide access to a derived class.
    Last edited by 7stud; 11-03-2005 at 07:34 PM.

  7. #7
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    Constructors are not inherited in the sense that it become a usable function of the child class. Since you are extending from the base class, chances are you will have more data, instantly making the constructor obsolete. The parent's constructor is not inherited, but is promised to be called upon creation of a child class.
    The "protected" access specifier means that that the member is private, but that it can be inherited by derived classes. So, if the method isn't inherited, why should a private member in another class be accessable?
    It does not mean that it can be inherited by a derived class, it means derived classes can have access to it. You inherit private members, you just can't touch them. This is why I don't understand why an instance of BaseDerived can't be created.

    My thought process:
    If the constructor is public, everbody can make a BaseDerived.
    If the constructor is protected, only friend and child classes can make a BaseDerived.
    If the constructor is private, only friend classes can make a BaseDerived.

    I could be very wrong, and you may be right in your last comment just above.

    Your code above also compiles on my system (MSVC++ 2003). What I would like to know is: if you uncomment the line where you declare a, does calling SomeFunc in DerivedProtected issue an error in 6.0?

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> if you uncomment the line where you declare a, does calling SomeFunc in DerivedProtected issue an error in 6.0?

    If you uncomment the line where you declare a, then that line causes an error in 6.0. The call to someFunc() doesn't. If you change a to be a DerivedProtected (meaning that line is no longer an error), and then call a.someFunc() inside DoStuff(), it works as it should.
    Code:
    void DoStuff()
    {
    	//BaseProtected a;// error
     
    	DerivedProtected a;// ok
     
    	a.someFunc(); // ok
    }
    If you call a.someFunc() from inside main(), it fails as it should.

  9. #9
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    Thank you for that info. MSVC++ 2003 does not have the same results.

    I find the same behavior if you deal with the = operator instead of the constructor. That is, you create your classes like normal, overloading the = operator in BaseProtected. If you try to call the BaseProtected = operator in DerivedProtected, it again squawks at you.

    Code:
    const DerivedProtected & operator = (const DerivedProtected & rhs)
    {
        *((BaseProtected*)this) =  *((BaseProtected*)&d); //can't access protected member
    }

  10. #10
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    I'm not sure if this is what you were trying to say 7stud, but I found this thread:
    http://groups.google.com/group/comp....&start=0&num=3
    and this one
    http://groups.google.com/group/comp....&start=1&num=3

    My understanding of inheritance was wrong. The reason for the error I was getting was this:
    A derived class can only access protected members of its base class IF ACCESSED THROUGH A REFERENCE OR A POINTER. Since you can't access a constructor through a pointer or reference, you can't use it period.

    The assignment operator can be used like so
    Code:
    void DerivedProtected::DoStuff(DerivedProtected & a)
    {
    	a.BaseProtected::operator =(*this);
    }
    I was never aware of that rule, since I very rarely pass a class by value. A derived class is able to use its own inherited protected members and methods because it accesses them through this, which is a pointer.

    But in light of all this confusion...I still found a bug in MSVC++ 2003 =). Calling the constructor of BaseDerived rightly issued an error, but that should have been the only line that had the error.
    Last edited by skorman00; 11-03-2005 at 09:22 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. Number to Word (Billions)
    By myphilosofi in forum C Programming
    Replies: 34
    Last Post: 02-04-2009, 02:09 AM
  3. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  4. char copy
    By variable in forum C Programming
    Replies: 8
    Last Post: 02-06-2005, 10:18 PM