In the following example, why am I unable to assign to the inherited variable a in my derived class bar?
#include <iostream>
class foo
{
protected:
int a;
};
class bar : public foo
{
public:
bar(int _a) : a{_a} {}
int GetA() const { return a; }
};
int main() {
bar b{5};
std::cout << b.GetA() << std::endl;
return 0;
}
I receive the following compiler error:
prog.cpp: In constructor 'bar::bar(int)':
prog.cpp:12:16: error: class 'bar' does not have any field named 'a'
bar(int _a) : a{_a} {}
^
Doesn't my bar class now have a variable bar::a? Or does it only have access to foo:a?
The compiler is correct. The class bar doesn't have any data members. It's parent does.
A traditional method is to use the Parent class' constructor:
class foo
{
protected:
foo(int value) : a(value)
{ ; }
int a;
};
class bar : public foo
{
public:
bar(int value)
: foo(value)
{ ; }
};
Another method is to access the foo variable in the constructor:
bar(int value)
{
foo::a = value; // parent scope added for emphasis.
}
You can access foo::a from the derived class bar, but not initialise it in the constructor's initialiser list. That can only initialise the base class directly. Thus, you should instead
class foo
{
protected:
foo(int _a) : a(_a) {} // initialise member
int a;
};
class bar : public foo
{
int b;
public:
bar(int _a) : foo{_a}, b(0) {} // initialise base, then member
int GetA() const { return a; } // fine: access protected member of base
};
Related
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 code:
#include <iostream>
class A {
private:
int a;
public:
void setA(int a_);
friend int B::getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int B::getA() {
return a;
}
int main() {
B myB;
myB.setA(9);
std::cout << myB.getA()<< std::endl;
return 0;
}
Compiling with g++ yields:
friend.cpp:10:16: error: use of undeclared identifier 'B'
friend int B::getA();
My thinking is that when the compiler is going through the class A definition, it does not yet know about class B. Therefore, I can forward declare B to take care of this problem:
#include <iostream>
class B;
class A {
...
That doesn't quite work:
friend.cpp:10:16: error: incomplete type 'B' named in nested name specifier
friend int B::getA();
It looks like the compiler isn't able to resolve the function as it is given.
How can I make a derived class function a friend in the base class?
Your code seems to violate the basic concept of data encapsulation. To resolve it, either make A::a protected, as #rici suggested, or define a getter in class A.
class A {
private:
int a;
public:
void setA(int a_);
virtual int getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int A::getA() {
return a;
}
int B::getA() {
return A::getA();
}
I have the following structure, and I would like to call foo from D. How is it possible? I got the error message, that I commented at the line below.
class A
{
protected:
class B
{
public:
B(x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
};
void bar()
{
D var = D(x);
var.foo(); //cant access protected member in class A::B
}
};
foo() is protected member function of B, means that foo() is only allowed to be called from its subclass( child class).
bar() is member function of C, and C is inheritance from A. So ,C is not subclass of B.
If you put bar in D, that's OK.As code below:
class A
{
protected:
class B
{
public:
B(int x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(int x) : B(x)
{
//empty
}
// Here is OK, while D is subclass of B
void bar()
{
int x;
D var = D(x);
var.foo(); //cant access protected member in class A::B
}
};
// void bar()
// {
// int x;
// D var = D(x);
// var.foo(); //cant access protected member in class A::B
// }
};
int main(){
return 0;
}
Try a friend class. You can make D a friend of B, and that should allow D to call foo().
Actually you are trying to access from the class C a protected method of the class D ==> You can't access protected methods from the external of a class.
One solution could be to declare C as a friend class of D so C can access protected methods:
// ...
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
// Declare C as friend of D
friend class C;
};
// ...
Adding the friendship declaration your code will compile and will work as expected.
You might want foo() to be public in D even though it is protected in A::B
If so you can add the following line after the public: line in the definition of D
using A::B::foo;
Thanks for the answer. Making the foo function public is really a solution, but I really want foo only available from inherited class. The friend modifier is a thing, what many people hate, because it gives you access for things, thats you should not access.
But also you were right guys, I should access B::foo from D (from constructor is not an option is my case). I could create a function, which calls the original foo, so my solution is:
class A
{
protected:
class B
{
public:
B(x)
{
//...
}
protected:
virtual void foo()
{
//...
}
};
};
class C : public A
{
protected:
class D : public A::B
{
public:
D(x) : B(x)
{
//empty
}
Dfoo()
{
B::foo();
}
};
void bar()
{
D var = D(x);
var.Dfoo();
}
};
The solution was easy, but I did not know that a function (what is not static) can be called like this :)
Given the following classes:
class foo
{
private:
int c;
public:
foo( int a = 42 ) { c = a; }
~foo();
};
class bar: public foo
{
public:
bar();
~bar();
};
How can I make bar override c with a different number? Can I do something like this?
bar::bar()
{
c = 12;
}
I get this error when trying to compile:
test.cpp: In constructor ‘bar::bar()’:
test.cpp:8:7: error: ‘int foo::c’ is private
Call your base class' constructor in the constructor initialization list:
bar::bar()
: foo(12)
{ }
Incidentally, you should always prefer using a constructor initialization list over assignment inside the constructor body, so your foo constructor would be better written as:
foo( int a = 42 ) : c(a) { }
Call the base class constructor:
bar::bar() : foo(12) { }
Edit: whoops
You should use getter and setter methods for your private variables.
So your calls foo should look like this:
class foo
{
private:
int c;
public:
foo( int a = 42 ) { c = a; }
virtual ~foo();
void setC (int tempC){
c=tempC;
}
int getC() const{
return c;
}
};
In the constructor of B you can call them the setter method:
bar::bar()
{
setC(12);
}
You should then always use your setter and getter methods to access your variable, instead of accessing it direct.
You should also declare your destructor of your base class virtual.
What about
bar::bar() : foo(12) {}
Say I have some code like this:
class Foo
{
public:
Foo(int v) : value(v) {}
Foo() : Foo(42) {}
private:
int value = 666;
};
Does the default ctor set value to 42 or 666? I guess I would hope for 42 since that is an explicit call but I could imagine the other way too.
How about with inheritance?
class Base
{
public:
Base() { }
virtual ~Base() { }
virtual int f() = 0;
};
class Bar : public Base
{
public:
Bar(int _i) : Base(), i(_i) { }
Bar() : Bar(-1) { }
virtual ~Bar() { }
virtual int f() { }
private:
int i = 777;
};
Again, I would hope for i == -1.
Thanks.
The in class body member initializer is just a default. If the member initializer list of a constructor initializes the member too, it takes precedence always.
This is specified by 12.6.2p9 in the C++11 spec.