I came across this code in a past exam:
#include <iostream>
class cls1
{
protected:
int x;
public:
cls1()
{
x = 13;
}
};
class cls2 : public cls1
{
int y;
public:
cls2()
{
y = 15;
}
int f(cls2 ob)
{
return (ob.x + ob.y);
}
};
int main()
{
cls2 ob;
std::cout << ob.f(ob);
return 0;
}
This works just fine and outputs 28. The problem is, it seems to contradict with this code (found in another exam):
#include <iostream>
class B
{
protected:
int x;
public:
B(int i = 28)
{
x = i;
}
virtual B f(B ob)
{
return x + ob.x + 1;
}
void afisare()
{
std::cout << x;
}
};
class D : public B
{
public:
D(int i = -32)
: B(i)
{
}
B f(B ob)
{
return x + ob.x - 1;/// int B::x is protected within this context
}
};
int main()
{
B *p1 = new D, *p2 = new B, *p3 = new B(p1->f(*p2));
p3->afisare();
return 0;
}
It's the same type of hierarchy, but one has access to ob.x and the other one doesn't. Can someone explain to me why that is?
The difference is, in the 1st case the protected member is accessed through the derived class. In the 2nd case the protected member is accessed through the base class, which is not allowed.
For protected members,
(emphasis mine)
A protected member of a class is only accessible
2) to the members and friends (until C++17) of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:
struct Base {
protected:
int i;
private:
void g(Base& b, struct Derived& d);
};
struct Derived : Base {
void f(Base& b, Derived& d) { // member function of a derived class
++d.i; // OK: the type of d is Derived
++i; // OK: the type of the implied '*this' is Derived
// ++b.i; // error: can't access a protected member through
// Base (otherwise it would be possible to change
// other derived classes, like a hypothetical
// Derived2, base implementation)
}
};
Related
Am geting the following error, "Use of deleted function 'Derived::Derived'" while executing the below code related to Inheritance. Also in the note it says, "Derived::Derived() is implicitly deleted because
the default definition would be ill informed". Can someone help me in fixing this:
#include <iostream>
//BASE CLASS
class Base
{
public:
int a;
void display()
{
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
}
//constructor
Base(int la, int lb, int lc) : a {la}, b {lb}, c {lc}
{
}
protected:
int b;
private:
int c;
};
//DERIVED CLASS
class Derived : public Base
{
//a from Base is Public
//b from Base is Protected
//c from Base has No access
public:
void access_base_members()
{
a = 100; //OK since a is Public in parent
b = 200; //OK since b is Protected type in Parent. So derived CLASS will have access
//c = 300; //NOK since c is private in parent and hence cannot be accessed
}
};
int main()
{
std::cout << "\nBase Member access=>\n\n";
Base base(1,2,3);
base.a = 10; //OK
//base.b = 20; //NOK since Protected
//base.c = 30; //NOK since Private
base.display();
Derived derived;
derived.a = 111; //OK since public in parent
//derived.b = 222; //NOK since protected members cannot have direct access in OBJECTS
//derived.c = 333; //NOK since private
}
The base class does not have the implicit default constructor because there is explicitly declared constructor
Base(int la, int lb, int lc) : a {la}, b {lb}, c {lc}
{
}
So the default constructor of the derived class that by default has to call the default constructor of the base class is defined as deleted.
Thus the compiler issues an error message for this declaration
Derived derived;
You need explicitly to define a constructor for the derived class.
For example you could define it like
Derived() : Base( 0, 0, 0 )
{
}
Or/and
Derived(int la, int lb, int lc ) : Base( la, lb, lc )
{
}
casting shared pointer from B class to A class is not working the console output isn't 12 it's (it outputs A's x but i want B's x)(probably an other memory address). what's wrong with my code
#include <iostream>
#include <memory>
class A
{
public:
int x;
};
class B : public A
{
public:
B(){}
B(const B*){}
int x = 12;
};
std::shared_ptr<A> create()
{
return std::make_shared<B>(new B);
}
int main(){
std::shared_ptr<A> p;
p = create();
std::cout << p->x << std::endl;
std::cin.get();
return 0;
}
A::x and B::x are different objects. Variable access is never polymorphic in C++, so when you access p->x, you're accessing A::x. A::x was never initialized though, so the behavior of your program is undefined.
You need to either have your derived class's constructor initialize the base class's object or delegate that responsibility to the base class's constructor:
class A
{
public:
A(int x) : x{x} {}
int x;
};
class B : public A
{
public:
B() : A{12} {}
};
Live Demo
Alternatively you could wrap x in a virtual accessor method:
class A
{
public:
virtual ~A() = default;
virtual int x() const = 0;
};
class B
{
public:
int x() const override
{
return x_;
}
private:
int x_ = 12;
};
Live Demo
I have the following design:
- one class A that has a protected member of class M.
- one class B that inherits from A and has a pointer to an object of class C
- one class C that needs to have access to the member of the class A
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
M _member;
}
class B : public A {
public:
B(){}
~B(){}
protected:
C* c;
}
class C {
// C needs to have access to _member
}
What design should be more appropriate to solve this issue ?
In pure OO terms, allowing a class to directly access the internal fields of another class is bad practice.
That said, C++ is not a pure OO language, and does allow for this (among other important deviations from OO).
To allow access to a private member to another class, you must designate that class to be a friend. Friendship, however is not passed to derived classes, therefore you must upcast the class to the type you need.
This is your simplest solution:
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
friend class C;
M _member;
}
class B : public A {
public:
B(){ c = new C(this); } // this call will cast the B* to an A* (important)
~B(){ delete c;}
protected:
C* c;
}
class C {
public:
C(A* a) { _a->_member = new M(); } //Now C can directly access _member in A
}
In such a way, any object derived from A can be turned back into an A* and used to access _member.
However, as previously stated, any classes derived from C will not gain access to _member, as friendship is not inherited, so a more comprehensive solution is required:
class M {
public:
void Foo() { printf("Foo called\n"); }
};
class A {
M* m;
friend class C;
public:
A():m(0) { ; }
};
class B :public A {
int id;
public:
B() { id = 0; }
};
class C {
public:
C() { _a = 0; }
C(A* a) { _a = a; }
protected:
M* getM() { return _a->m; }
void setM(M* m_) { _a->m = m_; }
private:
A* _a;
};
class D : public C {
public:
D(B* b): C(b) {
}
void Foo() {
setM(new M());
getM()->Foo();
delete getM();
setM(nullptr);
}
};
int main()
{
B* b = new B();
D d(b);
d.Foo();
delete b;
getchar();
return 0;
}
In this way, no classes derived from A provide direct access to _member, and no classes derived from C have direct access, but the member variable can still be accessed via C's protected API. This also prevents other external objects accessing it.
Make C a friend of A:
class A {
friend class C;
/*and so on*/
Then C can see all member variables and functions in A, even if they are private.
I have the following classes, and I'm trying to access a base member using an object of class H, and I get an H::a is ambiguous warning.
class E {
public:
E() : a(11) { }
int a;
};
class F : public E {
public:
F() : b(22) { }
int b;
};
class G : public E {
public:
G() : c(33) { }
int c;
};
class H: public F, public G {
public:
H() : d(44) { }
int d;
};
I tried making the data member a static, but then it doesn't let me initialize it in the base constructor. What's a solution to these two problems?
Class "H" has two variables called "a", one derived from F and one from G. You can either use a qualifier,
H::a
or you can use the "virtual" inheritance specifier (see https://stackoverflow.com/a/419999/257645)
#include <iostream>
struct A {
int a;
};
struct B : virtual public A {
};
struct C : virtual public A {
};
struct D : virtual public B, virtual public C {
void d1() { a = 1; }
void d2() { a = 2; }
};
int main() {
D d;
d.d1();
d.d2();
std::cout << d.a << std::endl;
}
http://ideone.com/p3LPe0
So I'm trying to write a copy constructor for class E such that it will get every int x from each class and assign it to its counterpart. How do I cast the right side?
class A
{
public:
int x;
};
class B: public virtual A
{
public:
int x;
};
class C: public virtual A
{
public:
int x;
};
class D : public B, public C
{
public:
int x;
};
class E: public D
{
public:
int x;
E(const E& e)
{
E::x = (E)e.x // problem
D::x = ?
C::x = ?
B::x = ?
A::x = ?
}
};
You do not need to cast an int to assign it to an int. Just do:
self->x = ((E)e).x;
D::x = ((D)e).x;
E::x = e.E::x;
D::x = e.D::x;
C::x = e.C::x;
B::x = e.B::x;
A::x = e.A::x;
Though it might be wiser to give each class a suitable copy constructor, with a suitable initialization list invoking copy constructors of base classes.