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() );
}
};
Related
I have a class inheriting from another. I don't want users of this class to accidentally use base-class functions on the child object. The obvious answer is to make the inheritance protected or private.
However, I do want implicit casting from the child object to the base class. The default implementation of this cast is hidden in most contexts as it's given the protected/private status, and attempting to define a user conversion throws the warning that
"converting ‘B’ to a reference to a base class ‘A’ will never use a type conversion operator [-Wclass-conversion]"
Fair enough. With that avenue closed to me, I must turn here and ask: is there some way to reclassify the default type conversion into the public space so that implicit casting can live on?
As an example of what I'm trying to get working:
class A
{
public:
A()
{
}
A(A& otherA)
{
}
};
class B : protected A
{
public:
operator A& ()
{
return *this;
}
};
int main() {
B guy;
A otherguy(guy);
}
Sadly, I can't just declare the offending functions within the base class as protected: I want them available if the user explicitly casts to that base class. In my particular case, B contains no data and is merely a convenience/safety wrapper around A, so I don't need to worry about slicing or otherwise losing any information by allowing this cast. I just don't want users mistaking the backend API (which is exposed currently via public inheritance) for parts of the more user-friendly wrapper API.
I don't think you can do what you want in the way you've asked to do it.
I'd use encapsulation instead of inheritance:
class A {
public:
T func1(); // should be visible via B
void func2(); // should not be visible via B
};
class B { // note: not inheriting from A
A base; // B explicitly defines its "base class sub-object"
public:
// provide access to base class sub-object
operator A&() { return base; }
// provide access to func1
T func1() { return base.func1(); }
};
void use(A &a) { a.func2(); }
int main() {
B b;
b.func1(); // no problem
// b.func2(); // won't work;
use(b); // no problem. Uses our conversion operator
}
I have a super Class (A) and two sub Class (B ,C)
an abstract Function in A have two difference return type in B and C!
How i have to Declare these??
return type is important
class A { //Super Class
public:
A();
virtual (some Type) QWERTY() = 0;
};
class B : public A { //Sub Class
public:
B();
double QWERTY();
};
class C : public A { //Sub Class
public:
C();
unsigned int QWERTY();
};
i'v to call sub Class function with super Class pointer
Since the functions are different in each sub-classes, you'll have to access them from pointers to those sub-classes.
This is exactly the kind of situation where dynamic_cast<> can help: it can conditionally convert a pointer from a base class to a sub-class if and only if it happens to be of the correct type:
void foo(A* a_ptr) {
B* b_ptr = dynamic_cast<B*>(a_ptr);
C* c_ptr = dynamic_cast<C*>(a_ptr);
if(b_ptr) {
b_ptr->QWERTY();
}
if(c_ptr) {
c_ptr->QWERTY();
}
}
It's, however, worth mentioning that this is some pretty ugly code, and might be suitable to solve the quiz you are presenting us, but in a normal environment, there are some design reevaluation that would happen before going to implement things this way.
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.
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();
}
class A {
public:
void fa() {
}
};
class B : public A{
public:
void fb() {
}
};
class C : public A, public B {
public:
void fc() {
//call A::fa(), not B::A::fa();
}
};
How to call A::fa() from C::fc() function.
GCC warns withdirect base A inaccessible in C due to ambiguity, does this mean there is no direct way to refer base class members?
One option would be to create a stub class that you can use for casting to the right base class subobject:
struct A {
void fa() { }
};
struct B : A {
void fb() { }
};
// Use a stub class that we can cast through:
struct A_ : A { };
struct C : A_, B {
void fc() {
implicit_cast<A_&>(*this).fa();
}
};
Where implicit_cast is defined as:
template <typename T> struct identity { typedef T type; }
template <typename T>
T implicit_cast(typename identity<T>::type& x) { return x; }
I just found the following info from ISO C++ 2003 standard (10.1.3)
A class shall not be specified as a direct base class of a derived class more than once. [Note: a class can be
an indirect base class more than once and can be a direct and an indirect base class. There are limited
things that can be done with such a class. The non-static data members and member functions of the direct
base class cannot be referred to in the scope of the derived class. However, the static members, enumerations
and types can be unambiguously referred to.
It means there is no direct way :(
I just compiled you code on codepad.org , putting A::fa() is enough to call fa() from your C::fc() function.
void fc() {
A::fa();
}
The below is the link to codepad with your code.
http://codepad.org/NMFTFRnt
I don't think you can do what you want. There is an ambiguity here: when you say A::fa(), it still doesn't tell the compiler which A object to use. There isn't any way to access class A. That's what the warning is telling you.
This seems like an awfully strange construct, though. Public inheritance should be used for is-a relationships. You are saying that C is-a A twice over? It doesn't make sense. And that suggests that this is either an artificial example that would never come up in practice, or you should reconsider this design.
You can use virtual inheritance to overcome such problem:
class B : virtual public A {
Now, you can use A::fa() simply in the child class C.
void fc()
{
fa();
}
However, I generally don't see any practical need to inherit class A again into class C, when B is already publically inheriting A. So, In your case, you can make it simple:
class C : public B {
Edit:
If you want 2 instances for A. then the direct instance which you are intending can be made as an object of C:
class C : public B {
A obj;
Because, having a directly inherited A will not be usable in anyway. You cannot declare any pointer or reference to it inside the scope of C.