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) {}
Related
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
};
I have a class like this:
//class1.h
class Foo
{
private:
int m_Value;
public:
int Foo();
}
//class1.cpp
#include "class1.h"
#define CONST_VARIABLE 12
Foo::Foo()
{
m_Value = CONST_VARIABLE;
}
and a derived class:
//class2.h
#include "class1.h"
class Foo2 : public Foo
{
puplic:
Foo2();
//other functions here
}
//class2.cpp
#define CONST_VARIABLE 24;
#include "class2.h"
Foo2::Foo2() : Foo()
{
}
However, when I called
Foo a;
Foo2 b;
Those 2 (a and b) have the same m_Value (which is 12).
I knew Foo2() will call Foo() first so m_Value will take the CONST_VARIABLE in class Foo. Thus, I try re-define it but with no luck.
Since both classes are initialized the same way but with different default values and I can't add parameter to the default constructor.
How can I create a derived class with same default constructor but with different value? And in the long run, I could easily maintain or modify the code by changing the the value quickly.
You could use a protected constructor so that only derived classes can use the constructor specifying a different member value:
class Foo {
public:
Foo();
protected:
explicit Foo(int value);
private:
int m_Value;
};
Foo::Foo() :
m_Value(12)
{}
Foo::Foo(int value) :
m_Value(value)
{}
class Foo2 {
public:
Foo2();
};
Foo2::Foo2 :
Foo(24)
{}
Adhering to your requirement that there is only a default constructor, you can accomplish that with a template. Assuming you have full control over your implementation:
template <int CONST_VALUE>
class FooT {
protected:
int m_Value;
FooT () : m_Value(CONST_VALUE) {}
};
class Foo : FooT<12> {
//...
};
class Foo2 : FooT<24> {
//...
};
If Foo2 must inherit from Foo directly, you can move the parts that need to be initialized into a super parent class, and then use virtual inheritance of it by Foo so that Foo2 can initialize the super parent directly. This avoids needing to implement two constructors in Foo (one default one, and one to let Foo2 dictate initialization).
class FooBase {
protected:
int m_Value;
FooBase (int v) : m_Value(v) {}
};
class Foo : public virtual FooBase {
public:
Foo () : FooBase(12) {}
//...
};
class Foo2 : public Foo {
public:
Foo2 () : FooBase(24) {}
//...
};
I want to call the constructor of a member m_foo of Class A in the constructor of Class A.
Is it nessecary to call it with m_foo = new Foo()? Or can I call it without putting it on the Heap?
I want to pass a pointer to an array of 256 Byte, so that the Foo object fills its member array with the data the pointer points to.
But how would I call a contructor of a member variable that I declare in the headerfile?
A.hpp
class A{
public
A();
private:
Foo m_foo;
};
A.cpp
A::A()
{
//How to call constructor of class Foo here?
}
Foo.hpp
class Foo()
{
Foo(char* p)
{
memcpy(m_Array, p, sizeof(m_Array)/sizeof(m_Array[0]));
}
private:
char m_Array[256];
};
Use the member initialization list for the A constructor :
A::A() : m_foo(...)
{
}
You can get the char* required to build m_foo from :
A constructor :
A::A(char* p) : m_foo(p) {}
Or another function :
A::A() : m_foo(GetBuffer()) {}
If you don't mind passing the pointer to A's constructor, this may be what you want:
class A
{
public:
A(const char* p);
private:
Foo m_foo;
};
A::A(const char* p) : m_foo(p) // <- calls Foo's ctor here
{
}
I have a class A which has a private method called a(). I have also a class B which needs to access a() (but just B should have access to a(), thats why a() is private). I could now use a friend specifier but that would make other private methods of A (lets call them b() and c()) also available to B and I dont want that behaviour.
Is there a way to make just a() of A accessable to B?
There is a way -- if your class has a public template function:
class A {
// apparently private
void priv () { std::cout << "got you A::a()" << std::endl ; }
public:
template <class T>
void abuse() {}
};
struct Thief {};
template <>
void A::abuse<Thief>() {
this->priv();
}
int main() {
A a;
// obviously do not compile : a.priv();
// this i OK
a.abuse<Thief>();
return 0;
}
I must confess I stole this from GotW...
No there's not, but as you specify the precise class, just B could access A's private members.
You just have to take care of what method are called.
As friend relationship are not inherited, you don't have to worry about B's possible subclasses.
This could be done with some "twist".
Just factor out method a() from A class into a parent class that has B as a friend class, then let A inherit it. this will leave a() as being a method in A, but the only private method accessible by its parent's friend B.
here is a very simple code to clarify what I've said:
class parent
{
friend class B;
private:
void a() {}
};
class A:public parent
{
private:
void b() {}
void c() {}
};
class B
{
A* m_a;
public :
B()
{
m_a = new A();
m_a->a(); // OK
m_a->b(); // error C2248: 'A::b' : cannot access private member declared in class 'A'
}
};
hope it helps !
Yes, I have an easy way. Let B have a pointer of A::a(), like this:
typedef boost::function<void ()> functype;
class A {
private:
void a();
};
class B {
public:
void setfp(functype f) {m_f = f;}
void foo() {
// do some stuff
m_f();
}
private:
functype m_f;
};
A a;
B b;
b.setfp(boost::bind(&A::a, &a));
b.foo();
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.