I have two user-defined classes:
class A:class Base
{
type x;
doSomething();
}
class B
{
type x;
doSomething();
}
I also have a function which gets a variable of type Base and use dynamic_cast to convert it to type A and use doSomething().
class D : class Base2
{
D(Base _base1):Base2(Base _base1)
{
//here is the actual problem
}
void foo()
{
//b is a private member of class Base2 of type Base
A *a=dynamic_cast(b);
A->doSomething();
}
}
but I want to pass B to this function ,and at the same time I don't want B to inherit from Base.
p.s I don't have access to change Base
how is this possible?
Casting between unrelated classes in not safe. The safest way to achieve what I think you're trying to do is to use a function template:
template <typename T>
void foo(const T& b)
{
b.doSomething();
}
Related
I want to retrieve the initial type in the base class A because the method encodeMsg() will have tasks that are related to the derived type
#include "stdafx.h"
#include <iostream>
struct base {
};
struct derive : base {
};
class A{
public:
A(){}
virtual void encode() {
encodeMsg(_bStruct);
// here I want to cast base to derive but I don't know how I tried
// static_cast<decltype(this)>(_bStruct) but it seems doesn't work
}
virtual void setStruct(base* bStruct) {
_bStruct = bStruct;
}
private:
virtual void encodeMsg(base* bStruct) = 0;
protected:
base* _bStruct;
};
class B : public A {
public:
B(){}
void encodeMsg(base* bStruct) {
derive* _dStruct = static_cast<derive*>(bStruct);
// ..
// stuff within dervied struct
_bStruct = static_cast<base*>(_dStruct); // turn back to base struct
}
};
int main() {
B b;
base* _bStruct = new derive();
b.setStruct(_bStruct);
b.encode();
return 0;
}
The question makes no sense.
In your code, the only thing you could do with the pointer, if you could create it, is access members known to be in the base class. But you can do that already without the pointer. So what purpose does the pointer serve?
If you want to one thing if it's a derived1 and something else if it's a derived2, then you need to use one piece of code for the derived1 case and one piece of code for the derived2 case.
If you want to do the same thing regardless of what derived type it is, there is no need for the cast you seek. The code in this function will be the same regardless of what the derived type is.
If you want code that only works if the derived type is some specific type, use a dynamic_cast to a pointer to that type and write the specific code. If you want code that works regardless of the derived type, use a pointer to an instance of the base class.
Update:
To access members not in base but in a derived1, use this code:
virtual void encode() {
derived1* d1 = dynamic_cast<derived1*>(bStruct);
if (d1 != nullptr)
{
// here you can access d1->whatever
}
}
Why this is not legal:
class Base
{
public:
Base(){};
virtual ~Base(){};
};
class Derived : public Base{};
void takeDerived(Derived * c){};
// main
void(*ptr)(Base*) = static_cast<void(*)(Base*)>(&takeDerived); // doesn't work
// but this work ok, as well as reinterpret_cast
// void(*ptr)(Base*) = (void(*)(Base*))(&takeDerived);
Derived is a Base. Why can't it be casted in function parameter? For example, I can do this easily even without casting:
void takeBase(Base* c){};
takeBase(new Derived{});
It's just designed to be that way. A Base isn't a Derived. The is-a relationship for class derivation can't be reversed.
The type of a function parameter means "accept", while the type of an object means "fit". Casting the type of a function changes what it accepts. It's dangerous to allow a function to accept whatever isn't what it originally accepts.
Consider this code:
class Base {};
class Derived : public Base {
public:
int t;
void useDerived() {}
};
void useDerived(Derived *d){
d->useDerived();
}
What should happen if a Base object is passed?
Base b;
((void(*)(Base*))useDerived) (&b);
Even worse, what if another derivation of Base is passed?
class AnotherDerived : public Base {
public:
double t;
void useDerived() {}
};
AnotherDerived ad;
((void(*)(Base*))useDerived) (&ad);
Yes, but you're trying to do it the other way around. You cannot do
void takeDerived(Derived *c) { }
...
Base b;
takeDerived(&b);
The function pointer cast you're trying to do would enable these shenanigans; you could do
void (*ptr)(Base*) = takeDerived;
Base b;
ptr(&b); // Oops.
Then things would explode, and that would be bad.
Given a base class Base that has two derived classes, DerA and DerB, can the derived classes have a member variable that is used in a Base member function, but is a different type for each class?
class Base {
* a // Declare a as *something*, so it can be used by "doWork"
template <typedef T>
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base {
// Make "a" an int
}
class DerB : public Base {
// Make "a" a float
}
In practice, a will be a base struct, while DerA and DerB will have derived versions of the base struct (derivative classes will each have a derived form of the struct specific to their purpose, but each must do a simple operation on a, so it seems pointless to copy/paste that simple function for each derivative when I can just use a template function). I would just type a as the base struct type, but then I lose access to the various specialized member functions and variables that each derived struct has (if I understand inheritance correctly).
I apologize if this question is a repeat, but I don't know what this quality would be called, so Googling proved fruitless.
What you might want is the CRTP.
template<class D>
struct Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork(T b) {
self()->a += b;
}
};
struct DerA : public Base<DerA> {
int a;
};
struct DerB : public Base<DerB> {
double a;
};
Here we pass the derived type to our base class. Within the base class, you can use self()-> to access fields in the derived type. This allows basically full access to the derived type, while letting us share code in the base class.
Note that you cannot pass DerA and DerB around as a Base this way. If you want that, you need a virtual method doWork, and virtual template methods don't exist.
CRTP stands for the curiously repeating template pattern, which I imagine is named because it is strange, it involves repeating a type, and it keeps on showing up in strange corners as being useful.
Type erasure probably won't work either, as you want to dispatch the type erasure from two different spots in the code base (the double dispatch problem: you need a centralized list of types supported to do the type Cartesian product on).
To expand on that, in order to support a+=b where both a and b are arbitrary types, you would have to expand over all types twice over, including types that are never mutually visible at the same spot in a compilation unit. That isn't possible.
If you need a common base, and there are only some types you pass to doWork, here is how you do it:
struct Base {
virtual void doWork( double ) = 0;
virtual void doWork( int ) = 0;
virtual void doWork( long long ) = 0;
};
template<class D>
struct Base_helper:Base {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
template<class T>
void doWork_impl(T b) {
self()->a += b;
}
void doWork( double x ) override { doWork_impl(x); };
void doWork( int x ) override { doWork_impl(x); };
void doWork( long long x ) override { doWork_impl(x); };
};
struct DerA : public Base_helper<DerA> {
int a;
};
struct DerB : public Base_helper<DerB> {
double a;
};
note that every version of doWork must be valid to call on each of the Ders, as the Base_helper instantiates all of them.
If the kind of type passed to doWork is unbounded, yet the types of Der is bounded, you can do something like the above only backwards. It gets awkward, however. Your best bet in that kind of situation is to use a boost::variant type solution.
I guess you want to achieve something like this:
template<typedef T>
class Base {
T a;
void doWork(T b) { // Add another value to "a" which is of its same type
a += b; // For example; an operation that works on "a", no matter what numeric type it is
}
}
class DerA : public Base<int> {
}
class DerB : public Base<float> {
}
Or you can dump classes DerA and DerB entirely and use typedefs instead:
typedef Base<int> DerA;
typedef Base<float> DerB;
This can be easily solved with a CRTP-like pattern:
template<class D> // Base class is templated
class Base {
public:
D a;
void doWork(D b) {
a += b;
}
};
class DerA : public Base<int> {};
class DerB : public Base<float> {};
Live Example
Edit: in case you need only one common base (Base<int> is a completely different type from Base<float>) you might use an interface class and have Base inherit from it.
How to implement casting to a private base class in C++? I don't want to use hacks such as adding a friend etc. Defining public casting operator does not work.
EDIT :
For example I have:
class A {
//base class
}
class AX : private A {
//a child
}
class AY : private A {
//another specialized child
}
class B {
//base class
void do (A a) {//do
}
}
class BX : private B {
//a child
void do (AX a) {
B::do( static_cast <A> (a) );
}
}
class BY : private B {
//another specialized child
void do (AY a) {
B::do( static_cast <A> (a) );
}
}
EDIT2
Why do I do this?
Suppose I have to define some property which is quite heavyweight and can be of several similar types (like VelocityX VelocityY etc). Then I want to be able to have classes which can have any set of these properties. If I want to process these properties, it is obvious, that I'd rather cast them to their base type than to add an implementation for each variation. I do not use public inheritance because it's better to explicitly cast where needed than to have the private interface implicitly visible. Not a real problem but I'd like to have a solution :)
If defining a public casting operator does not work, you can try with a regular function:
class D: private B {
public:
B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...
Anyway, what is the point? If D derives privately from B, then you are not supposed to use a D as a B from the outside.
You can just use a C-style cast. No need for any "hacks" or "implementations". Wrapping it into an explicit function serves the "C-Style casts are bad" people
template<typename Targ, typename Src>
typename boost::enable_if<boost::is_base_of<Targ, Src>, Targ>::type &
private_cast(Src &src) { return (Targ&)src; }
To have the cast safe, you need to ensure that Targ is actually a private or public base. This is done by boost::is_base_of.
Of course you should prefer member functions in the respective derived class that return the base pointer, instead of doing such a cast..
Defining public casting operator does not work.
That doesn't make sense to me... Why make the base class private at all then? Just make it public. The reason your conversion functions don't work is because the Standard requires that implicit conversions never consider conversion functions to a base class, the class itself or void.
I have a use case for this; I am inheriting from a large and volatile base class that is adding functions all the time and almost never is the base class function going to work correctly in my subclass, so I inherit privately.
I think it's simplest just to make a function that returns the base class. Below I list a fully corrected program; please try compiling your code before submitting a question, since using identifiers like "do" as function names is likely to make every compiler unhappy .. :-( :-(
class A {
//base class
};
class AX : private A {
//a child
public:
A *ToA() { return this; }
};
class AY : private A {
//another specialized child
public:
A *ToA() { return this; }
};
class B {
//base class
protected:
void do_it (A a) {};
};
class BX : private B {
//a child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};
class BY : private B {
//another specialized child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};
Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.