Lets say I have a class A that has a member of type int.
I have a class B which is a subclass of A.
B is meant to initialize the members to some state and has no other purpose.
#include <string>
#include <iostream>
struct A {
int someInt;
A() : someInt(33){}
};
struct B : public A {
B() {
someInt = 4;
}
};
int main() {
A a = A();
A b = B();
std::cout<< a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
Notice how I use A b = B() where object slicing should occur.
However since B doesn't add anything to A, is it a valid alternative to using A with different constructor parameters (or any other form of creating instances of A)?
Edit:
The background is that I have a class that has some complex setup.
Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder.
More common and less error prone method is to define static methods to create your class instances:
struct A {
static A makeA();
static A makeB();
};
int main()
{
auto a = A::makeA();
auto b = A::makeB();
}
and to prevent even more errors you may want to prohibit creation of instances of A directly, rather than set of static methods by making A ctor private.
To answer your question as directly as possible, what you're doing is certainly "valid" in the sense that it will compile and run and produce a correct result. It's probably not the most common way to accomplish this though.
My recommendation for a more idiomatic approach would be to use a common base class and templatize all of your derived versions. Basically make the compiler do the work of setting the integer value you want.
struct ABase {
int someInt;
ABase() = delete;
ABase(int initVal) : someInt(initVal) { }
};
template<int T>
struct A : public ABase {
A() : ABase(T) {}
};
int main() {
ABase a = A<33>();
ABase b = A<4>();
std::cout << a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
This is probably less code overall (especially if you have more than just two versions of this class), and much more flexible.
As a better practice,
Use another constructor in class A and this constructor will take parameters OR Use a separate function in class A to do what you want.
And regarding "Putting the initialization into separate child class is way easier than lets say write a constructor, factory or builder" doesn't make sense in this situation, so it's not easier even the code is complex as you said.
Related
The library I am using defines an abstract base class A with ~10 pure virtual methods. There are no non-pure methods publicly defined and I suspect that A has no private data, i.e. the class is merely an interface. The library also defines a few concrete sub-classes of A, such as C.
I would like to add some functionality to A so that all of its sub-classes inherit this functionality. However, A is defined in the library and I cannot do this.
Instead, I have defined a new sub-class of B. This sub-class is not concrete and all of the pure virtual methods of A are left alone. It defines a few new helper methods that call out to the methods defined by A. There are also no fields defined by B.
In order to use B to augment the functionality of instance of C I have done the following, which I suspect is not guaranteed behavior.
Create an object of type C on the heap.
Cast the pointer to this object to instead be of type B*.
Return this pointer, exiting the local scope where the object was created.
Call methods defined by B using this pointer in a different scope.
Is this safe? The objects are created on the heap, so I don't think any slicing will happen. If the safety depends on which fields A and C define, what requirements are needed to guarantee this behavior?
If neither A nor C had their own data other than the vpointer, would this be safe?
What about if only C has its own data?
Edit: I should add that I have attempted this and the behavior has at least seemed to be what I want. I have not profiled for memory leaks though.
The whole thing looks like code smell to me. I would take the approach for B class of a wrapper class: take an A* pointer in the constructor, forwarding the calls you need to that A*. Then you can pass a C* to that constructor, that will be correctly deleted through a "delete" in B destructor.
Here is one idea following up on my comment. It behaves as intended, might be some hidden dangers but to me it seems reasonable as long as bar does not hold any data.
#include <iostream>
struct base {
int x = 1;
int y = 2;
void show() {
std::cout << x + y << std::endl;
}
virtual void virt() = 0;
};
struct foo : base {
int a = 5;
int b = 2;
void print() {
std::cout << a + b << std::endl;
x++;
}
void virt() override {
std::cout << "foo" << std::endl;
}
};
template <typename T>
struct bar : T {
void print2() {
std::cout << T::a * T::b << std::endl;
T::b++;
T::x++;
T::virt();
}
};
template <typename Base>
bar<Base>* extend_with_bar(Base& base) {
return static_cast<bar<Base>*>(&base);
}
int main() {
foo f;
f.show();
f.print();
auto b = extend_with_bar(f);
b->print2();
b->print2();
b->print();
f.print();
b->show();
f.show();
b->virt();
}
Disclaimer: I'm a long time C programmer moving into C++, so it's very likely/possible there is a better way to do this.
I would like to create a class A with 1 to N members of class B. In most cases, I'm fine calling class B's member functions. However, in some cases I would like to override a member function in class B. Is there an elegant way to do this without having to create a derived class from class B every time?
Here is an example:
using namespace std;
#include <iostream>
class B
{
public:
void print();
};
void B::print()
{
cout << "B::print" << endl;
}
class A
{
public:
B b;
B bprime;
};
int main()
{
A a;
a.b.print();
a.bprime.print();
return 0;
}
Is there a way to override the print() function in bprime or otherwise change it? In C, I would have left class B as a struct and used function pointers, but I'd like to avoid that here.
You can use std::function to simulate polymorphism.
class B
{
public:
std::function<_FUNCTION_SIGNATURE_HERE_> print;
};
then you can always override print member in an instance of B
a.bprime.print = SomeOTherFunctionWithSameSignature;
and from this moment on bprime will behave as if it was a different subclass in a hierarchy. Everything will work the same, except this particular function you changed.
Of course you will have to set initial behavior of print member in your constructor.
I am interested if it is safe, to DOWNCAST (thanks Mike) an instance of a base class to a derived class under certain conditions. I think a sample is the most easy way to explain:
struct BaseA
{
void foo() const {}
double bar_member;
// no virtuals here
};
struct DerivedA : public BaseA
{
double bar(double z) {bar_member = z;return bar_member;}
// DerivedA does not add ANY member variables to BaseA.
// It also does not introduce ANY virtual functions.
};
struct BaseB
{
BaseA baseA;
};
// add extra functionality to B, to do this,
// i also need more functionality on baseA.
struct DerivedB : public BaseB
{
// is this "safe"? since BaseA and DerivedA
// should have the same memory layout?!?
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
#include <iostream>
int main(int argc, char** argv)
{
DerivedB b;
// compiles and prints expected result
std::cout << b.foo(argc) << std::endl;
}
In my case, the classes BaseA and BaseB implement some kind of view concept. However, they also hold all the data members required to add further functionality in the derived classes. I know that I could implement the view to hold only a reference to the class providing the functionality. However, that would comes with some drawbacks:
I need to rewrite the whole interface for the view classes.
In my case, the Derived classes possesses an extra template argument (a callback type), which I want to have erased in the view. Hence, the view must not hold a direct reference to the classes providing functionality.
I tested my code, it works, however, I don't really trust the approach. And yes, I know I could achieve some of this with virtuals etc. but it is really performance critical...
Any ideas, hints, are welcome
Martin
for the interested people:
i changed my design the following way:
struct DerivedB : public BaseB
{
// encapsule the required extended functionality of BaseA member
struct OperateOnBaseA
{
OperateOnBaseA(BaseA& a);
double dosomething(double);
};
OperateOnBaseA a_extension;
DerivedB() :a_extension(baseA) {}
double foo(double z) {return a_extension.dosomething();}
};
As to the technical side: It is of course forbidden by the 2011 standard, 5.2.9.11, static cast. Let B be a base of D:
If the prvalue of type “pointer to cv1 B” points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
On the other hand I'd be surprised if somebody could find an implementation which doesn't just do it, because of the obvious implementations of classes, methods and static casts.
Your existing code has undefined behaviour, as stated in the other answers. You can avoid that, if you don't mind some truly horrible code, by destroying the object at baseA and creating a DerivedA at the same location, so the downcast is valid:
#include <new>
struct DerivedB : public BaseB
{
DerivedB()
{
static_assert( sizeof(BaseA) == sizeof(DerivedA), "same size" );
baseA.~BaseA();
::new(&baseA) DerivedA();
}
~DerivedB()
{
getA().~DerivedA();
::new(&baseA) BaseA();
}
DerivedA& getA() {return *static_cast<DerivedA*>(&baseA);}
double foo(double z) {return getA().bar(z);}
};
The destructor restores an object of the original type, so that when the BaseB destructor destroys its baseA member it runs the destructor of the correct type on the object.
But I would avoid doing this and redesign your classes to solve it another way.
I don't find your approad clean enough for what you're trying to do. Assuming there's a "data source type" SourceA and a "data view type" ViewB, I would go more like this:
#include <iostream>
using namespace std;
template<typename T>
class SourceA_base
{
protected:
T data;
public:
using value_type = T;
SourceA_base(T&& a) : data(std::move(a)) { }
SourceA_base(T const& a) : data() { }
void foo() const {}
};
template<typename T>
class SourceA : public SourceA_base<T>
{
using B = SourceA_base<T>;
public:
using B::B;
T bar(T z) { return B::data = z; }
};
template<typename U>
class ViewB_base
{
protected:
U&& source;
public:
using value_type = typename std::remove_reference<U>::type::value_type;
ViewB_base(U&& a) : source(std::forward<U>(a)) { }
};
template<typename U>
class ViewB : public ViewB_base<U>
{
using B = ViewB_base<U>;
using T = typename B::value_type;
public:
using B::B;
T foo(T z) { return B::source.bar(z); }
};
int main ()
{
using S = SourceA<double>;
S a{3.14};
ViewB<S&> b{a};
std::cout << b.foo(6.28) << std::endl; // compiles and prints expected result
std::cout << ViewB<S>{S{2}}.foo(4) << std::endl; // still works
}
That is, all (source/view) types are templated, views contain references, and there are no downcasts. On your reservations for the use of references:
Re-writing the whole interface: No need now, thanks to templates.
Erasing callback types: First, type erasure and performance critical applications are not always good friends. Second, you'd better have the callback erase its own underlying type(s), not the view erase the type of the callback. Each class should do its own job. Or, don't erase types and make them template parameters.
I used rvalue-references so that the whole thing works for temporaries as well, as shown in my second example. Maybe constructors are not always complete/correct here. e.g. for const references; I reality would have fully templated constructors (accepting universal references), but to make this cooperate with one-argument implicitly defined copy/move constructors is a bit trickier (needs type traits and enable_if) and I only wanted to hightlight the idea here.
You may also consider using tuples to hold data, taking advantage of their empty base optimization.
As for your original question, this downcast is something I would never do; for the technical side, see Peter Schneider's answer.
I am trying to understand inheritance and I need some help building two classes. The fist one is called A, the second one is called B.
A has one private integer value "m_a". It has two constructors, the default one sets m_a to 5. and another one which takes as an argument an integer called m and sets m_a's value to m. As for member functions it will have two. The first one will return m_a. The second one will print "Hello from A!". Let's move on to B. B will have a private string m_s. A default constructor which will set m_s to "asd" or to anything other than an empty string and a constructor which will take as an argument a string and set m_s to it's value. As far as functions go, firstly B will have a function that will return m_s. It will have a function which will have the same name as the print "Hello from A" function in A which will override it and it will printout "Hello from B!" instead (is that polymorphism ?).
Those are the classes needed. I have the following questions (I will post what I have created below)
Firstly, is there any way I can get to the private data fileds from the base class. For example let's say I want to take the m_s variable, add it to another one and print out their sum. Is that possible ? (and how)
Also when I try to create a class with a constructor different from the default one I get errors. I am obviously doing something wrong. The question is what.
I think those are all of my questions for now, so it is time for me to post the source code.
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
int m_a;
public:
A(){m_a = 5;}
A(int m)
{
m_a = m;
}
void pm()
{
cout << "Hello from A!" << endl;
}
int get_a()
{
return m_a;
}
};
class B : A
{
private :
string m_s;
public:
B(){m_s = "asd";}
B(string s)
{
m_s = s;
}
void pm()
{
cout << "Hello from B!" << endl;
}
string get_s()
{
return m_s;
}
};
int main()
{
A a(10);
a.pm();
cout << a.get_a() << endl;
B b("asd");
b.pm();
cout << b.get_s() << endl;
cout << b.get_a() << endl;
return 0;
}
(is that polymorphism ?).
Not the way you have done it. It would be polymorphism if you had a pointer of type A* which pointed to what was actually a B object, and calling pm on that pointer correctly invoked the member function of B. This would only be possible if the pm function in A were declared as virtual, like below.
class A
{
...
virtual void pm(){
...
};
...
int main()
{
A* = new B();
A->pm(); //"Hello from B!"
}
is there any way I can get to the private data fileds from the base class
Not sure what you mean here - your example talks of a private field of the derived class.
Typically good class design means that derived class should not need to access the (private) fields of the base class, if this is needed you should make that field protected.
As to the compile error #ArunKumar got it exactly.
When you say Class B : A You inherit from A, but all the members are inherited as private by default, due to this, base class constructor is private, so you cannot use it.
However when you say Class B : public A it is the other end of the spectrum. All members of the base class retain their accesibility in the derived class (public remains public, etc)
The problem is that you're using private inheritance:
class B : A {
Inheritance through classes are private by default. Add public before A.
class B : public A {
As for your other problem...
I want to take the m_s variable, add it to another one and print out their sum.
This is easy when it comes to std::string. Just create another member function:
void addTom_s(string s) { m_s += s; }
Trying changing class B : A to class B : public A
Lets say we have the following two class definitions.
#include <iostream>
#include <array>
class A
{
public:
virtual void f() = 0;
};
class B : public A
{
public:
virtual void f() { std::cout << i << std::endl; }
int i;
};
Here sizeof(B) == 8, presumably 4 the virtual pointer and 4 for the int.
Now lets say we make an array of B, like so:
std::array<B, 10> x;
Now we get sizeof(x) == 80.
If my understanding is correct, all method calls on elements of x are resolved statically, as we know the type at compile time. Unless we do something like A* p = &x[i] I don't see a need to even store the virtual pointer.
Is there a way to create an object of type B without a virtual pointer if you know it is not going to be used?
i.e. a template type nonvirtual<T> which does not contain a virtual pointer, and cannot be pointed to by a subtype of T?
Is there a way to create an object of type B without a virtual pointer if you know it is not going to be used?
No. Objects are what they are. A virtual object is virtual, always.
After all, you could do this:
A *a = &x[2];
a->f();
That is perfectly legitimate and legal code. And C++ has to allow it. The type B is virtual, and it has a certain size. You can't make a type be a different type based on where it is used.
Answering my own question here, but I've found that the following does the job, by splitting A into it's virtual and non-virtual components:
enum is_virtual
{
VIRTUAL,
STATIC
};
template <is_virtual X>
class A;
template<>
class A<STATIC>
{
};
template<>
class A<VIRTUAL> : public A<STATIC>
{
public:
virtual void f() = 0;
virtual ~A() {}
};
template <is_virtual X>
class B : public A<X>
{
public:
void f() { std::cout << i << std::endl; }
int i;
};
The important thing here is that in B<> don't specify f() as virtual. That way it will be virtual if the class inherits A<VIRTUAL>, but not virtual if it inherits A<STATIC>. Then we can do the following:
int main()
{
std::cout << sizeof(B<STATIC>) << std::endl; // 4
std::cout << sizeof(B<VIRTUAL>) << std::endl; // 8
std::array<B<STATIC>, 10> x1;
std::array<B<VIRTUAL>, 10> x2;
std::cout << sizeof(x1) << std::endl; // 40
std::cout << sizeof(x2) << std::endl; // 80
}
That would be a nice one to have, but I can't think of any way to revoke virtual members or avoid storing the virtual pointer.
You could probably do some nasty hacks by keeping a buffer that's the size of B without the virtual pointer, and play with casts and such. But is all undefined behavior, and platform dependant.
Unfortunately it won't work in any normal sense as the code inside the method calls expects the virtual pointer to be in the class definition.
I suppose you could copy/paste all of A and B's code into a new class but that gets to be a maintenance headache fast.