I want to fill a constexpr table with pointers to call the pointers later. The given example shows only one entry.
I run into two problems:
1) It is not possible for me to find a correct syntax to write a pointer a member class object which is able to initialized to an object of a derived class.
2) I could not use the pointer to call the virtual functions.
#include <iostream>
using namespace std;
class State { public: virtual void Do() const {} };
class S1: public State { public: virtual void Do() const { cout << "S1 Do" << endl; } };
class S2: public State { public: virtual void Do() const { cout << "S2 Do" << endl; } };
class A
{
public:
S1 s1;
S2 s2;
};
class B
{
private:
static constexpr A a{};
static constexpr State A::*state { &A::S2 }; // < do not work!
public:
void Do() const
{
(a.*state).Do(); // is it possible to have a pointer to any State class to call virtual functions?
}
};
constexpr A B::a;
int main()
{
B b;
b.Do();
return 0;
}
I think the issue is an oversite in the standard. There's no
reason why:
State A::*state = static_cast<State A::*>( &A::s1 );
shouldn't work, but the wording to allow it is missing in the
standard. There are a number of work-arounds: the most obvious
would be to have an accessor function returning a State* for
each member variable, and use a pointer to the function:
class A
{
public:
S1 s1;
State* getS1() { return &s1; }
S1 s2;
State* getS2() { return &s2; }
};
class B
{
static A a;
static State* (A::*getState)();
public:
void Do() const
{
(a.*getState)()->Do();
}
}
State* (A::* B::getState)() = &A::getS1;
Related
Suppose I have a base class that is an abstract interface, and two derived classes, which inherit a certain state from the base class. I want to change which derived class I'm using at run-time, but I want to preserve the shared state.
class Base{
public:
virtual void abstract() = 0;
SharedState ss;
};
class Der1 : public Base{
Der1() = default;
virtual void abstract() {//bla bla};
Der1(SharedState &s){
ss = s;};
};
class Der2 : public Base{
Der2() = default;
virtual void abstract(){//bla bla 2};
Der2(SharedState &s){
ss = s;};
};
struct SharedState{
int x,y,z;
float x1,y1,z1;
//etc...
}
I my handler code, I have a smart pointer that changes behaviour based on class type at run-time, hence the shared state constructor.
//driver code
std::unique_ptr<Base> ptr = std::make_unique<Der1>();
I'm planning to change the type, but with such a constructor I can preserve the state. However it is highly annoying to preface every member of the shared state with ss., is there a way to avoid this, perhaps with a using declaration of some sort?
Edit: I know I can move the shared state in the base and make it static, but that leads to performance drops when I'm not using this interface.
This is an ugly answer, but is an answer, solves the "ss" problem and can be usefull.
I overloaded the operator [] to directly return the values of your struct
struct SharedState{
int x,y,z;
float x1,y1,z1;
//etc...
};
class Base{
public:
virtual void abstract() = 0;
SharedState ss;
public:
int& operator[](const std::string rhs)
{
if(rhs == "x") //Here you will manage all the struct members, probably a map
return this->ss.x; // return the result by reference
}
};
class Der1 : public Base{
void abstract() override { };
public:
Der1(SharedState &s){
ss = s;};
};
class Der2 : public Base{
void abstract() override { };
public:
Der2(SharedState &s){
ss = s;};
};
int main()
{
SharedState ss;
ss.x = 100;
std::unique_ptr<Base> ptr = std::make_unique<Der1>(ss);
std::cout << (*ptr)["x"] << std::endl;
(*ptr)["x"] = 5; // You can change it too
std::cout << (*ptr)["x"] << std::endl;
std::unique_ptr<Base> ptr2 = std::make_unique<Der2>(ptr->ss);
std::cout << (*ptr2)["x"] << std::endl;
}
I do not understand why the following code does not work since *p is dynamically a B object.
class A {
public:
bool test() {return true;}
};
class B : public A {
public:
bool test() {return false;}
};
int main() {
A* p = new B;
std::cout << p->B::test();
return 0;
}
I know I could use virtual but I believe this is not the point. The compiler says I should define a second constructor or a conversion operator. What can I do ?
*p is dynamically a B object, but with declaration A* p and usage p->test(), A::test() is statically linked at compile time.
If you want dynamic dispatch at runtime, you have to use virtual functions.
#include<iostream>
class A {
public:
bool test() { return true; }
virtual int count() { return 42; }
};
class B : public A {
public:
bool test() { return false; }
virtual int count() { return 100; }
};
int main() {
A* p = new B();
std::cout << p->test() << std::endl; // A::test() is called
std::cout << p->count(); // B::count() is called
}
In the example, functions bool test() will be dispatched statically, while int count() will be dispatched dynamically.
Please consider the following piece of code:
#include <iostream>
#include <string>
enum Type { T1, T2 };
class Base {
public:
std::string baseName;
Type type;
Base(const std::string& bn, Type t):
baseName(bn), type(t) {}
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Base(bn, Type::T1), dName("Dervied1"+dn) {}
int getX(void) const { return x; }
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Base(bn, Type::T2), dName("Derived2"+dn){}
int getY(void) const { return y; }
};
void func(Base& b)
{
if (b.type == Type::T1)
{
Derived1& d1 = static_cast<Derived1&>(b);
std::cout << d1.baseName << " " << d1.dName << " " << d1.getX();
std::cout << std::endl;
}
else
{
Derived2& d2 = static_cast<Derived2&>(b);
std::cout << d2.baseName << " " << d2.dName << " " << d2.getY();
}
};
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
The requirement is to have a function that can take in the base class value and then depending on the "type" of the derived instance, do something different. My question is - is this the right way of doing things or am I missing some important design pattern. I remember reading that use of static_cast or dynamic_cast means that there is something inherently wrong with the design. I understand that ideally the base class can have virtual functions that the derived classes implement, and at run time they get polymorphically dispatched. However, in this case there are two functions in each derived class that are specific to those classes, viz. getX and getY. How can I change the design to make it better and perhaps not use the cast?
Thanks!
The requirement is to have a function that can take in the base class value and then depending on the "type" of the derived instance, do something different.
That is exactly what polymorphism is all about. But you are not using it the way it is meant to be used.
My question is - is this the right way of doing things
No.
am I missing some important design pattern.
This would be better handled by getting rid of Type altogether and introduce a virtual method in Base.
I understand that ideally the base class can have virtual functions that the derived classes implement, and at run time they get polymorphically dispatched.
Exactly.
However, in this case there are two functions in each derived class that are specific to those classes, viz. getX and getY.
So? Using polymorphism correctly does not prevent that.
How can I change the design to make it better and perhaps not use the cast?
Use polymorphism correctly. For example:
#include <iostream>
#include <string>
class Base
{
public:
std::string baseName;
Base(const std::string& bn):
baseName(bn) {}
virtual void doIt() = 0;
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Base(bn), dName("Dervied1"+dn) {}
int getX(void) const { return x; }
void doIt() override
{
std::cout << baseName << " " << dName << " " << getX();
std::cout << std::endl;
}
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Base(bn), dName("Derived2"+dn) {}
int getY(void) const { return y; }
void doIt() override
{
std::cout << baseName << " " << dName << " " << getY();
}
};
void func(Base& b)
{
b.doIt();
}
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
And then take it a step farther by moving common code around so it can be shared by the derived classes:
#include <iostream>
#include <string>
class Base
{
public:
std::string baseName;
Base(const std::string& bn):
baseName(bn) {}
virtual void doIt()
{
std::cout << baseName;
}
};
class Derived : public Base
{
public:
std::string dName;
Derived(const std::string& bn, const std::string& dn):
Base(bn), dName(dn) {}
void doIt() override
{
Base::doIt();
std::cout << " " << dName;
}
};
class Derived1 : public Derived
{
public:
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Derived(bn, "Dervied1"+dn) {}
int getX(void) const { return x; }
void doIt() override
{
Derived::doIt();
std::cout << " " << getX();
std::cout << std::endl;
}
};
class Derived2 : public Derived
{
public:
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Derived(bn, "Derived2"+dn) {}
int getY(void) const { return y; }
void doIt() override
{
Derived::doIt();
std::cout << " " << getY();
}
};
void func(Base& b)
{
b.doIt();
}
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
If you have the option of using a virtual member function, as outlined by the other answer, it is the best approach to use. However, there are situations where you don't have that luxury. In that case, you can build your dispatch mechanism based on the type of the derived type.
#include <iostream>
#include <string>
#include <map>
class Base {
public:
std::string baseName;
Base(const std::string& bn): baseName(bn) {}
virtual ~Base() {}
// Don't store type ID per instance.
// Make it a virtual function so derived classes
// can return the same value for each instance.
virtual int getTypeID() = 0;
// Helper function for derived classes to use so each
// derived class can have a unique type id associated
// with it. This eliminates the need for having an enum.
static int getNextTypeID();
{
static int typeID = 0;
return ++typeID;
}
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn,
const std::string& dn):
Base(bn), dName("Dervied1"+dn) {}
// get type ID for this class.
// Every instance of the class will return
// same value.
virtual int getTypeID()
{
return getTypeIDStatic();
}
// This is a crucial piece of function
// that allows type based dispatch mechanism to work.
static int getTypeIDStatic()
{
static int typeID = Base::getNextTypeID();
return typeID;
}
int getX(void) const { return x; }
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn,
const std::string& dn):
Base(bn), dName("Derived2"+dn){}
int getY(void) const { return y; }
virtual int getTypeID()
{
return getTypeIDStatic();
}
static int getTypeIDStatic()
{
static int typeID = Base::getNextTypeID();
return typeID;
}
};
// Define a function type.
using Function = void (*)(Base& b);
// Keep a registry of functions that can be called for
// different types derived from Base.
std::map<int, Function>& getRegisteredFunctionsMap()
{
static std::map<int, Function> functionsMap;
return functionsMap;
}
// Provide a mechanism to register functions for types
// derived from Base.
template <typename T>
void registerFunction(Function f)
{
getRegisteredFunctionsMap()[T::getTypeIDStatic()] = f;
}
void func(Base& b)
{
// Check whether there is a function base on the type of b.
std::map<int, Function>& functionsMap = getRegisteredFunctionsMap();
std::map<int, Function>::iterator iter = functionsMap.find(b.getTypeID());
if ( iter != functionsMap.end() )
{
// If yes, call it.
iter->second(b);
}
else
{
// No function to deal with the type.
// Deal with the situation.
}
};
// A function that can be called when the real type is Derived1.
void derived1Fun(Base& b)
{
// Assume that b is derived.
Derived1& d1 = dynamic_cast<Derived1&>(b);
// Now use d1.
std::cout << d1.baseName << " " << d1.dName << " " << d1.getX();
std::cout << std::endl;
}
// A function that can be called when the real type is Derived2.
void derived2Fun(Base& b)
{
// Assume that b is Derived2.
Derived2& d2 = dynamic_cast<Derived2&>(b);
// Now use d2.
std::cout << d2.baseName << " " << d2.dName << " " << d2.getY();
std::cout << std::endl;
}
int main(void)
{
// Register functions for Derived1 and Derived2.
registerFunction<Derived1>(derived1Fun);
registerFunction<Derived2>(derived2Fun);
// Make the function calls.
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
Output of running the above program:
Base Dervied1foo 10
Base Derived2foo 20
I am trying to do something like this with c++.
void showContensofArray(void *data[])
{
//In this function have to display the values of respective objects.
// Any ideas how do I do it?
}
int main(){
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
void *dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray); //function
}
If you want to treat the objects in the data[] generically (i.e by calling a common function on them to extract a description or values) then define a class hirachy for your objects and in your showContentsofArray function call virtual methods on your (common base class) object pointers.
This is a textbook example of Polymorphism:
"polymorphism allows values of different data types to be handled using a uniform interface."
In the example below the base class BaseObject defines the uniform interface.
class BaseObject {
virtual string description() { return "Base object"; }
virtual bool bounces() { return false; }
}
class B : public BaseObject {
string description() { return "Im a B object" }
bool bounces() { return true; }
}
class A : public BaseObject {
string description() { return "Im an A object" }
}
void showContensofArray(BaseObject* data[], int size) {
for (int i=0; i<size; i++) {
cout << data[i]->description();
if (data[i]->bounces())
cout << "I bounce!";
}
}
int main() {
A phew(xxx,abcdefg); //object of class A
B ball(90),ball2(88); //object of class B
BaseObject* dataArray[2];
dataArray[0] = &ph1;
dataArray[1] = &ball;
showContentsofArray(dataArray);
}
Will output:
Im an A object
Im a B object
I bounce!
void showContensofArray(void *data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
And every Class should have an implementation of the method print() that knows how to print its values.
You could also use inheritance.
EDIT:
#Ricibob's answer is correct, but if you need to do the casting inside the function, you need to do something like this:
#include <iostream>
using namespace std;
class Base{
public:
virtual void print()=0;
};
class A: public Base{
public:
void print(){
cout<<"Object A"<<endl;
}
};
class B: public Base{
public:
void print(){
cout<<"Object B"<<endl;
}
};
void showContensofArray(void* data[], int len)
{
int i;
for(i=0;i<len;i++){
((Base*)(data[i]))->print();
}
}
int main(){
A a;
B b;
void* v[2];
v[0]= &a;
v[1] = &b;
showContensofArray(v,2);
return 0;
}
You can't evade inheritance.
Just cast back to the original type:
A* p1 = static_cast<A*>(data[0]);
B* p2 = static_cast<B*>(data[1]);
I'm having a very odd problem that I'm hoping someone has come across.
class Letter
{
public:
Letter()
virtual ~Letter()
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A()
~A()
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l }
private:
Letter * letter;
}
int main()
{
Board b;
b.setLetter(new A());
}
The program causes a seg fault when Board goes out of scope at the line where the virtual function letter->get() is called in the destructor. I'm using gcc 4.1.2. Any ideas?
UPDATE
Okay, it seems what's actually happening in the real code is the equivalent of this:
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter* letter;
};
int main()
{
Board b;
A a;
b.setLetter(&a);
return 0;
}
In which case A is already out of scope when the virtual function is called.
I can only guess you're attempting to cast the std::string returned from get() to a char*. Otherwise i see no reason for the crash.
#include <iostream>
#include <string>
using namespace std;
class Letter
{
public:
Letter() {}
virtual ~Letter() {}
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A() {}
~A() {}
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter * letter;
};
int main()
{
Board b;
b.setLetter(new A());
return 0;
}
no problem in gcc 4.5.2
I didn't realize an object was being passed to setLetter() from the stack, so A was going out of scope before b.
Board b;
A a;
b.setLetter(&a);
Some compilers doesn't allow Plain C / C++ constructors or destructors call virtual methods, seems like the (ANSI) C++ specification neither. And its not recommended.
Sometimes that requirement is useful. Some languages like Object Pascal explicit allow virtual methods calls within constructors and destructors.
One thing you can do its use the "Fake Virtual Constructor Pattern":
class MyClass
{
public:
// constructor
MyClass
{
// anything but virtual methods
}
// destructor
~MyClass
{
// anything but virtual methods
}
virtual void MyFakeConstructor()
{
MyVirtualMethod();
}
virtual void MyFakeDestructor()
{
MyVirtualMethod();
}
virtual void MyVirtualMethod()
{
// more stuff
}
// more members
}
int main(char[][] Args)
{
MyClass MyObject = new MyClass();
MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"
MyObject->DoSomething1();
MyObject->DoSomething2();
MyObject->DoSomething3();
MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
delete MyObject;
return 0;
} // int main()
Another solution its that you arrange your code so you explicit call your virtual method outside the destructor.
Cheers.