This question already has answers here:
Overriding static variables when subclassing
(8 answers)
Closed 8 years ago.
I want each class to have its own static code, which can be requested from each object. I am thinking of this, but it doesn't seem to work:
#include <iostream>
class Parent {
protected:
static int code;
public:
int getCode();
};
int Parent::code = 10;
int Parent::getCode() {
return code;
}
class Child : public Parent {
protected:
static int code;
};
int Child::code = 20;
int main() {
Child c;
Parent p;
std::cout << c.getCode() << "\n";
std::cout << p.getCode() << "\n";
return 0;
}
It outputs:
10
10
yet I expect
20
10
You have to make the 'getCode()' function as virtual and have to implement every time as following codes:
class Parent {
protected:
static int code;
public:
virtual int getCode() { return code; }
};
int Parent::code = 10;
class Child : public Parent {
protected:
static int code;
public:
virtual int getCode() { return code; }
};
int Child::code = 20;
int main()
{
Child c;
Parent p;
std::cout << c.getCode() << "\n";
std::cout << p.getCode() << "\n";
return 0;
}
class Parent {
public:
virtual int getCode();
// Looks like a variable, but actually calls the virtual getCode method.
// declspec(property) is available on several, but not all, compilers.
__declspec(property(get = getCode)) int code;
};
class Child : public Parent {
public:
virtual int getCode();
};
int Parent::getCode() { return 10; }
int Child::getCode() { return 20; }
int main() {
Child c;
Parent p;
std::cout << c.code << "\n"; // Result is 20
std::cout << p.code << "\n"; // Result is 10
return 0;
}
Why use the member variable at all?
class Parent {
public:
static int getCode();
};
int Parent::getCode() {
return 10;
}
class Child : public Parent {
public:
static int getCode();
};
int Child::getCode() {
return 20;
}
Instead of one static member per class, you have one member function per class. Plain and simple.
Your problem:
In the parent class, you don't declare your getCode function as virtual.
So, whenever you call it with a class that inherits from your parent class,
it will just return the int code from the parent class.
To fix this:
First, declare the getCode function as virtual in your parent class.
Second, write another getCode function in your inherited class and return
the int code from the inherited class
Related
I write c++ with c++11 and have a question as title.
Ex.
class Hi {
public:
Hi(){};
test() {cout << "test" << endl;};
}
void noop(){
; // noop
};
int main(){
Hi hi();
hi.test = noop; // just example, not real case
return 0;
}
Is that possible to replace test() of class Hi to a noop function in runtime!? Thanks.
You can't replace any function at runtime, whether class member or not.
However, you can achieve the desired effect by using a variable.
(This is yet another example of the "add a level of indirection" method of solving problems.)
Example:
class Hi {
public:
Hi(): test([this]() { do_test(); }) {}
std::function<void()> test;
void do_test() { cout << "test" << endl; }
};
void noop(){}
int main(){
Hi hi;
hi.test(); // Outputs 'test'
hi.test = noop;
hi.test(); // Does nothing
}
You have to think object oriented. In this case you have to elevate your function to be an object we can name it MethodClass then your function in the class Hi will be a pointer to that class. Below a simple example
#include <memory>
class BaseMethodClass
{
public:
virtual void method() = 0;
};
class MethodClass1 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class MethodClass2 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class Hi
{
public:
Hi() { method = nullptr; };
void setMethod(BaseMethodClass* m) { method.reset(m); }
void test() { if (method) method->method(); };
private:
std::shared_ptr<BaseMethodClass> method;
};
int main()
{
Hi hi;
hi.setMethod(new MethodClass1());
hi.test();
hi.setMethod(new MethodClass2());
hi.test();
return 0;
}
This way you can override your methos as you want not just noop
I have to type in below the missing constructor for class Child that will initialize all member variables when object child{1,2} is instantiated from the class in the main program.
I know this->b = b should work, however, I have problems when trying to set the a value equal to the private member int a in class Parent. Sorry if my directions aren't too clear.
#include <iostream>
using namespace std;
class Parent
{
private:
int a {0};
public:
Parent() = default;
Parent(int a) {this->a = a;}
int getA()
{ return a; }
};
class Child : public Parent
{
private:
int b {0};
public:
Child() = default;
//missing constructor
int getB()
{ return b; }
};
int main()
{
Child child{1,2};
int holdA = child.getA();
int holdB = child.getB();
cout << "Int a is " << holdA << " and Int b is " << holdB << endl;
return 0;
}
#include<iostream>
using namespace std;
class Base {
private: int b;
protected: int a;
public: int c; void setdata(); int getdata(); };
void Base ::setdata() { int a = 10; int b = 20; int c = 30; }
int Base::getdata() { return b; }
class Derived: public Base { public: void display() { setdata(); cout << a << endl << getdata() << endl << c << endl; } };
int main() { Derived xyz; xyz.display(); return 0; }
Lets look at your setdata function:
void Base ::setdata() { int a = 10; int b = 20; int c = 30; }
Inside it you define three new variables a, b and c, which are totally unrelated with the Base member variables of the same name.
That means the Base member variables will be uninitialized and with indeterminate values. And printing them leads to undefined behavior.
Your setdata function should set the Base member variables, which are already declared and defined and can be used as-is:
void Base ::setdata() { a = 10; b = 20; c = 30; }
With that said, a better solution is to use a constructor to initialize the member variables instead of a separate function:
class Base
{
public:
Base()
: a{ 10 }, b{ 20 }, c{ 30 } // An initializer list, to initialize members
{
// Empty body of constructor function
}
// Rest of class, without the setdata function ...
};
I need an array of pointers to member functions in a base class like this
class Base {
public:
typedef int(Base::*func)();
func f[3];
Base();
void run();
};
void Base::run()
{
cout << (this->*f[0])() << endl;
cout << (this->*f[1])() << endl;
cout << (this->*f[2])() << endl;
}
The function run() will be the same for all child classes. But pointers in the array f[] will refer to member functions that will be defined in the child classes.
class Child: public Base {
public:
typedef int(Child::*func)();
func f[3];
int A();
int B();
int C();
Child();
};
int Child::A()
{
return 1;
}
int Child::B()
{
return 2;
}
int Child::C()
{
return 3;
}
Child::Child()
{
f[0] = &Child::A;
f[1] = &Child::B;
f[2] = &Child::C;
}
If I run this code in program I get problems
Child x;
x.run();
How to do this?
This works:
class Base {
public:
typedef int(Base::*func)();
func f[3];
virtual int A() { return 0; }
virtual int B() { return 0; }
virtual int C() { return 0; }
Base() {};
void run()
{
cout << (this->*f[0])() << endl;
cout << (this->*f[1])() << endl;
cout << (this->*f[2])() << endl;
}
};
class Child: public Base {
public:
int A() { return 1; }
int B() { return 2; }
int C() { return 3; }
Child()
{
f[0] = &Base::A;
f[1] = &Base::B;
f[2] = &Base::C;
}
};
You're facing two major obstacles here.
One, you never initialize the Base::f but that is what run operates on. You declare a member f in the child class and initialize it in the constructor. The Base classes f is never initialized, and is filled with garbage. When you call run, it tries to use those random values. This is undefined behavior.
Two, int(Base::*)() and int(Child::*)() are two distinct and incompatible types. You look like you want to fill the array with pointers to child functions and call them from the base class.
There are a couple ways to fix this:
You could make run virtual and implement it in the child class to call the functions.
You could put the functions in the base class and make them virtual, so pointers to them will call the derived versions.
You could make an array of std::function objects instead of pointers.
My scenario is simplified in the following example:
#include <iostream>
#include <vector>
using namespace std;
class C;
class A
{
protected:
C * cPointer;
A();
virtual void updateList() = 0;
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
public:
void callFromA();
};
class C
{
friend class A;
friend class B; // I want to get rid off this declaration
private:
int sum;
void set_sum( int val );
public:
static C * getCPointer();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
int s = 0;
for( unsigned int i=0; i<list.size(); i++ )
{
s += list[i];
}
cPointer->set_sum(s);
}
void B::callFromA()
{
callFunc();
}
void C::set_sum( int val )
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return & cPointer;
}
int main( int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
This example works fine. But I want to get rid of the "friend class B" declaration in class C and achieving similar functionality. Actually I want to have either of the following:
accessibility of C::set_sum() from B::updateList() which will not be possible without the "friend class B" declaration in class C.
accessibility of B::list in A::callFunc() whereby I can push the logic from B::updateList to A::callFunc() which basically means ability to access a list in the derived class from the base class. In this way, I will be able to access the set_sum() in A::callFunc() due to "friend class A" declaration in class C.
Any idea to achieve this without involving major design changes is desirable!
Thanks!
I'm not sure if I understand all your restrictions, but maybe this works better for you. Basically, you can access B::list from A using a virtual function. I've commented the changes in the code.
#include <iostream>
#include <vector>
using namespace std;
class A;
class C
{
friend class A;
private:
int sum;
void set_sum(int val);
public:
static C * getCPointer();
};
class A
{
protected:
C * cPointer;
A();
virtual int getS() = 0; // virtual function to calculate data from vector in derived class B
virtual void updateList()
{
cPointer->set_sum(getS()); // A is friend of C, so you can access B data from A
}
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
int getS() // concrete implementation to access vector data
{
int s = 0;
for (unsigned int i = 0; i < list.size(); i++)
{
s += list[i];
}
return s;
}
public:
void callFromA();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
A::updateList(); // Call to super implementation
}
void B::callFromA()
{
callFunc();
}
void C::set_sum(int val)
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return &cPointer;
}
int main(int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
You can not access members of derived classes inside the base class, period. The object at hand might be of the base class, or even of a completely unrelated derived class, with guaranteed "interesting" consecuences. Any design asking for doing so is seriously broken, and needs rethinking.
You can make the member function of the base class which wants to do so virtual, and redefine it in the derived class to do whatever perversion you have in mind. Meanwhile, the chaste member of the base class can just refuse if called, signalling the mistake in a sane way. That way you get a guarantee that nothing too untoward can happen.