say I have this example :
class A1
{
private:
string name;
}
class A
{
private:
A1* field;
}
class B1 : public A1
{
private:
int id;
}
class B : public A
{
private:
B1* field;
}
so in this case I would have in my B class:
id attribute from the B1 class
name attribute coming from the inheritance of the class A.
another name attribute coming form the inheritance of B1 class from the class A1.
So what should I do to avoid this redundancy ?
I don't see any redundancy here. Let's rename the classes into something more useful:
class Animal // A1
{
private:
string name;
}
class Person // A
{
private:
Animal* housePet;
}
class Dog : public Animal // B1
{
private:
int breedId;
}
class DogTrainer : public Person // B
{
private:
Dog* trainee;
}
You see, no field can be safely eliminated. The trainee is not the same as the housePet, each of them needs a separate name.
No, you haven't any redundancy.
B class didn't inherit any member from its base classes because they have been declared as private (then visible and accessible only from within the class they are declared).
For example:
class A
{
private:
int _privateMember;
protected:
int _protectedMember;
public:
int _publicMember;
};
class B : public A
{
void test()
{
// This doesn't work, this field is private to the class
// where it has been declared (A)
_privateMember = 1;
// This works, a protected member is accessible inside the class
// where it's declared and derived classes.
_protectedMember = 1;
// This works, a public member is always visible and accessible.
_publicMember = 1;
}
};
void test()
{
A a;
// This doesn't work, a private field isn't accessible outside the class
// where it has been declared
a._privateMember = 1;
// This doesn't work, a protected member is accessible only inside the class
// where it has been declared and its derived classes
a._protectedMember = 1;
// This works, a public member is always visible.
a._publicMember = 1;
}
Things can be more complicated than this, you do not need to always use public inheritance, for example:
class C : protected A
{
};
void test()
{
C c;
// This doesn't work! Field is public for its class but C has inherited from A
// in a protected way (so only derived classes know that it derives from A).
c._publicMember = 1;
}
Moreover you can make all private members of a class visible to another class or function using the friend declaration:
class D
{
private:
int _privateMember;
public:
int _publicMember;
friend class DFriend;
};
class DFriend
{
void test()
{
D d;
// This works, public members are accessible
d._publicMember = 1;
// This works too, this class is a friend of D
d._privateMember = 1;
}
};
That said remember that when you derive from a base class you say "derived class is of type base class". For example you have a base class to describe a planet with some properties (modeled for simplicity as public fields):
class Planet
{
public:
int Diameter;
};
Then suddenly you discover you have to make it more general and you add a more general base class called CelestialBody:
class CelestialBody
{
public:
bool canCapture(CelestialBody anotherBody)
{
// Some calculations
}
private:
vector<CelestialBody> _capturedBodies;
};
class Planet : public CelestialBody
{
public:
int Diameter;
};
Now you say this:
A celestial body is something that can capture another celestial body;
A celestial body keeps a private list of captured bodies because they may change some of its properties.
A planet is a celestial body.
A planet has a public (integer) property to describe its diameter in Km.
Private members of CelestialBody aren't visible outside of it (kind of implementation details). World knows that a Planet is a CelestialBody (because of public inheritance) then everything was public in CelestialBody is public in Planet too.
If you do not want to say this then you shouldn't simply use inheritance. Take a look to this articles:
Composition and inheritance: when to inherit from another object and when to include another object as field.
Incapsulation: incapsulation of informations inside a class.
Related
I have a class Animal, which has a subclass Dog, which has a subclass BigDog. The class Animal has a protected int legs. I am unable to access legs in the BigDog class functions or constructor.
class Animal {
protected:
int legs = 0;
Color eyeColor = Color(0,0,0);
public:
virtual string getSound() const = 0;
};
class Dog : Animal {
public:
string getSound() const override {
string sound = "";
int legI = legs;
while (legI-- > 0) {
sound+=" *step* ";
}
sound+="BARK";
return sound;
}
Dog() : Animal() {
legs = 4;
eyeColor = Color(200,128,0);
}
};
class BigDog : Dog {
public:
//use the initializer of dog
BigDog() : Dog() {
legs = 4;
}
string getSound() const override {
string sound = "";
int legI = legs;
while (legI-- > 0) {
sound+=" *step* ";
}
sound+="BOOF BOOF";
return sound;
}
};
This code gives "error: ‘int Animal::legs’ is protected" when setting or reading legs from BigDog
When you write
class Dog : Animal { … };
what you're really writing is
class Dog : private Animal { … };
because the default access specifier for classes defined with class-key class is private [class.access.base]/2 (fancy way of saying: if you have a class that class will inherit everything to be private unless you explicitly say otherwise). Private inheritance means all protected and public members of the base class will be private in the derived class. Since Dog inherited all the Animal stuff privately, it's not accessible to BigDog anymore (which, by the way, also inherits all the Dog stuff privately). What you most likely wanted to write is
class Dog : public Animal { … };
and
class BigDog : public Dog { … };
Note: if you had a struct, the default would be public.
You're using private inheritance, which implies that every inherited member becomes private. You want public inheritance.
class Dog : public Animal {
...
class BigDog : public Dog {
Note the keyword public here, which ensures that public members remain public and protected members remain protected. The access specifier for inheritance specifies the maximum visibility of any inherited member, so when it's private everything will be private. And, like with members of class classes, if you don't specify, the inheritance will assume that you mean private. More on that on cppreference.
I have a struct obj in my base class. I don't know how to access the data members of the struct through Derv1 class (Derived from the base class). I tried making both Base and Derv1 a friend of struct - it still tells me ' data member is private' (its private in Base only).
example :
struct A{
public :
int total;
//some stuff
};
class MyClass{ // [Base] class
private:
A var1;
};
class Derv1{
private:
//some stuff
public void display_var1(Derv1 x){
return x.var1.total;
} // trying to return the value of A.total
};
I hope this makes sense so that you can help me out ..
Thank You kindly,
First, you have to make sure that Derv derives from MyClass.
class Derv1 : public MyClass { ... };
and then, you will need to figure out the best way to display the variable.
My suggestion:
Create a virtual member function in the base class.
Override the function in the derived class.
Make sure to call the base class implementation in the derived class implementatin.
class MyClass { // [Base] class
public:
virtual void display() const
{
// Display var1 anyway you wish to.
}
private:
A var1;
};
class Derv1 : public MyClass {
public:
virtual void display() const
{
// Call the base class implementation first
MyClass::display():
// Display anything else that corresponds to this class
}
private:
//some stuff
};
i think you must extend your Derv1 class into the Base class:
class Derv1: public MyClass{
to inherit the members of the base class
The rules state that an in the case of a public specifier - object of derived class can be treated as object of base class (not vice-versa). What does that mean?
Can all public elements (in any class) be accessible by anything/anywhere?
Does this refer to the fact that for the parent class attributes and methods defined as public are accessible by the derived class. But in the case that the attributes and methods from the derived class are public they aren't accessible by the parent/base class?
In a public base class
Base class members How inherited base class members appear in derived class
private: x ------------------------> x is inaccessible
protected: y ------------------------> protected: y
public: z ------------------------> public: z
but what about in reverse?
I suppose the correct question would be "Can members (not objects) of derived classes in C++ be accessible by parent class?"
Public and protected members (data members and functions) of the base class are accessible to the derived class.
Public members of a class are accessible from anywhere. Of course, they need to be accessed through an instance of that class.
But in the case that the attributes and methods from the derived class are public theyaren't accessible by the parent/base class?
They can be if you have an instance of the derived class. You can then access the public members of the derived class from the base class.
Edit:
Example where base class member accesses public member of derived class and vice versa.
class Base
{
public:
void funcBase();
};
class Derived : public Base
{
public:
void funcDerived();
};
void
Base::funcBase()
{
Derived d;
d.funcDerived();
}
void
Derived::funcDerived()
{
Base b;
b.funcBase();
}
int main()
{
Base b;
Derived d;
b.funcBase();
d.funcDerived();
}
It means if you have Bar that is a derived class of Foo.
class Foo
class Bar : public Foo
So you can say, as expected
Foo* myFoo = new Foo;
Bar* myBar = new Bar;
You can also make a Foo from a Bar since a Bar is a type of Foo
Foo* myOtherFoo = new Bar;
You cannot make a Bar from a Foo, that is what "object of derived class can be treated as object of base class (not vice-versa)" means.
Bar* myOtherBar = new Foo;
You asked:
Can objects of derived classes in C++ be accessible by parent class?
Yes. See below for a pattern that I have seen a few times.
You also asked:
Can all public elements (in any class) be accessible by anything/anywhere?
Yes, of course.
Example pattern of base class accessing derived class members
Entity.h:
class Attribute;
class Entity
{
public:
Entity(Attribute* att);
void save(FILE* fp);
void print();
private:
Attribute* att_;
};
Attribute.h:
#include "Entity.h"
class Attribute : public Entity
{
public:
void save(FILE* fp);
void print();
};
Entity.cc:
#include "Entity.h"
#include "Attribute.h" // Needed to access Attribute member functions
Entity::Entity(Attribute* att) : att_(att) {}
void Entity::save(FILE* fp)
{
// Save its own data.
//...
// Save the Attribute
att_->save(fp);
}
void Entity::print()
{
// Print its own data to stdout.
//...
// Print the Attribute
att_->print();
}
I am put/get value in/from subclass B from object of base class A. But I am not able to assign or get the value. My code is:
class A
{
};
class B: A
{
string SID;
};
class C: A
{
string Name;
};
class D : A
{
string Name;
};
class E
{
A a;
UINT32 AccessLevel;
};
.......
main()
{
E e;
}
Using object of e am trying to get the value of subclass B.
I need to get the SID from the class B?
Thanks,
The C++11 standard 11/3 says:
Members of a class defined with the keyword class are private by default.
at 11.2/2
In the absence of an access-specifier for a base class [...] private is assumed when the class is defined with the class-key class.
and at 11.2/1:
If a class is declared to be a base
class for another class using the private access specifier, the public and protected members of the base
class are accessible as private members of the derived class.
So what does that mean? First of all:
class A {};
class B : A {};
Here A, by virtue of 11.2/2 is inherited privately. This may be okay if you want to inherit variables and you want to implement getter/setters for a variable only in a derived class, but that's usually considered bad style.
In your case however, as stated by 11/3, your members are not inherited at all because they are private members:
class A
{
public:
int a; // inherited
protected:
int b; // inherited
private:
int c; // NOT inherited
};
and especially
class A { int a; };
is equivalent to
class A { private: int a; };
So you could make your members accessable from within your derived classes by making them public or protected (see 11.2/1):
class A { public: int a; };
class B : A {}; // privately inherits a
and if you wanted to make it acessable from outside of your derived classes you will have to inherit as public as well:
class A { public: int a; };
class B : public A {}; // publicly inherits a
but that's not what you usually would do. It's considered better style to make variables private and expose only getters and setters for those:
class A
{
public:
int get_a() const { return a_; }
void set_a(int val) { a_ = val; }
private:
int a_;
};
class B : public A {}; // now publicly inherits the getters and setters
// but not a_ itself
let's say we have class A,B,C,D where A is base, B,C are between and D is derived in diamond model.
NOTE:
class B inherits virtualy class A in private mode,
class C inherita virtualy class A in protected mode.
class A
{
public:
int member; // note this member
};
class B :
virtual private A // note private
{
};
class C :
virtual protected A // note protected
{
};
class D :
public B, // doesn't metter public or whatever here
public C
{
};
int main()
{
D test;
test.member = 0; // WHAT IS member? protected or private member?
cin.ignore();
return 0;
}
now when we make an instance of class D what will member be then? private or protected lol?
Figure No2:
what if we make it so:
class B :
virtual public A // note public this time!
{
};
class C :
virtual protected A // same as before
{
};
I suppose member will be public in this second example isn it?
§11.6 Multiple access [class.paths]
If a name can be reached by several paths through a multiple inheritance graph, the access is that of the path that gives most access. [ Example:
class W { public: void f(); };
class A : private virtual W { };
class B : public virtual W { };
class C : public A, public B {
void f() { W::f(); } // OK
};
Since W::f() is available to C::f() along the public path through B, access is allowed. —end example ]
I think I don't need to add anything else, but see also this defect report (which was closed as "not a defect").