I want to write a class A with two methods b and c.
The method b calls c.
I want to be able to replace c with anything I like.
I think I can do that if I make c a function pointer or virtual method.
However, b will be called for many times. Will these two solutions affect the performance?
Is it possible to redesign this to avoid using function pointers/virtual methods?
Test inheritance:
#include <iostream>
class A {
public:
A() {}
void b() { c(); }
void c() { std::cout << "1\n"; }
};
class B : public A {
public:
void c() { std::cout << "2\n"; }
};
int main() {
B b;
b.b();
}
Result:
1
Not 2.
Edit: I want to specify what c does at compile time. There are multiple forms of c that I want to plug into the same b method.
Both virtual functions and function pointers suffer from the same performance problems.
First, it is the general inability for compiler to inline those calls. Generally compiler will have to do real function calls and assume side effects, so a lot of optimization techniques can't be performed. Often the impact is quite significant.
Second, during code execution, CPU will generally not be able to prefetch code past the pointer call - since it won't know where the execution will be transferred to. However, hardware call devirtualizers, similar to branch predictors, try to speculatively prefetch instructions based on past performance, and after several calls they are trained and do a good job there. However, lack of inlining still bites you.
If you want no performance penalties, you could use CRTP:
template <typename Derived>
class A {
public:
A() {}
void b() { static_cast<Derived*>(this)->c(); }
void c() { std::cout << "1\n"; }
};
class B : public A<B> {
public:
void c() { std::cout << "2\n"; }
};
int main() {
B b;
b.b();
}
Live example: https://onlinegdb.com/SJzxbtqjz
However, this might not be what you want - it all depends on your use case, which I cannot tell from your question. Make sure you read the pitfalls section on the wikipedia page I linked above:
One issue with static polymorphism is that without using a general
base class like "Shape" from the above example, derived classes cannot
be stored homogeneously as each CRTP base class is a unique type. For
this reason, it is more common to inherit from a shared base class
with a virtual destructor, like the example above.
EDIT:
Otherwise, you'll need to do what you suggested, and pay the price of going through a function pointer. However, if the function you are calling is not something very simple, you probably won't see a difference in performance.
EDIT 2:
The compiler will completely inline the call toc() with appropriate optimizations.
GCC 7.3 with -O2 optimization flag, and a bit simpler code (just to avoid complexity of std::cout):
template <typename Derived>
class A {
public:
A() {}
int b() { return static_cast<Derived*>(this)->c(); }
int c() { return 1; }
};
class B : public A<B> {
public:
int c() { return 2; }
};
int f() {
B b;
return b.b();
}
will generate no code for class B, and generate the following assembly for f:
f():
mov eax, 2
ret
Live example: https://godbolt.org/g/Mh99bZ
Template solution:
#include <iostream>
struct X1 {
static void c() { std::cout << "1\n"; }
};
struct X2 {
static void c() { std::cout << "2\n"; }
};
template <class X>
class A {
public:
A() {}
void b() { X::c(); }
};
int main() {
A<X1> a;
a.b();
A<X2> b;
b.b();
}
Result:
1
2
Solution with reference and template.
It is better than just template because the method c can use the attributes within the class X1.
#include <iostream>
class X1 {
public:
X1(int v) { _v = v; }
void c() {
std::cout << "X1: " << _v << "\n";
}
int _v;
};
template <typename X>
class A {
public:
A(X& x) : _x(x) {}
void b() { _x.c(); }
private:
X& _x;
};
template <typename X>
A<X> make_A(X& x) { return A<X>(x); }
int main() {
X1 x1(10);
// A a1(x1); ///< need c++17
auto a = make_A(x1); ///< works for c++11
a.b();
}
Result:
X1: 10
Related
The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.
#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.
when running the following code on MSVC 2013, x64 Debug config, it will show up a message box with this famous error message when quitting the main() function
"Run-Time Check Failure #2 - Stack around the variable 'tmp' was corrupted.".
The question I can't answer is: Why?
note that no error message will occur when running on Release config. (why?)
disclaimer: this is just a sample code, meaning that I'm trying to use this same design on other classes (one base and several derived) with much more methods and template arguments and with a much more complex data type than the basic int*.
#include <iostream>
template <class T>
class base {
public:
base() {
static_cast<T*>(this)->setData();
}
~base() {
static_cast<T*>(this)->destroyData();
}
void print() {
static_cast<T*>(this)->print_int();
}
};
class derived : public base<derived> {
public:
void setData() {
x = new int();
}
void destroyData() {
delete x;
x = nullptr;
}
void print_int() {
std::cout << "x = " << *x << std::endl;
}
private:
derived() {}
derived(const derived& other) {}
inline derived& operator= (derived copy) {}
int *x;
};
int main() {
base<derived> tmp;
tmp.print();
return 0;
}
EDIT:
#Yakk if I understand correctly, you propose as solution this code:
#include <iostream>
template <class T>
class mix_in : public T
{
public:
mix_in() { (this)->setData(); }
~mix_in() { (this)->destroyData(); }
void print() { (this)->print_int(); }
};
class foo
{
public:
void setData()
{
x = new int();
}
void destroyData()
{
delete x;
x = nullptr;
}
void print_int()
{
std::cout << "x = " << *x << std::endl;
}
foo() {}
private:
int *x;
};
int main()
{
mix_in<foo> tmp;
tmp.print();
return 0;
}
It works just fine, thank you. I'll probably use this pattern since it seems that there's no solution to use CRTP for what I'm trying to do.
But I still would like to understand why the stack corruption happens. In spite of all the discussion around use or not use CRTP for all things, I'd like to understand very precisely why it happens.
Thank you again.
As for your code shown in main():
int main() {
base<derived> tmp;
tmp.print();
return 0;
}
base<derived> tmp; that's wrong usage of this pattern, you wanted derived tmp;.
The point of the CRTP is that the derived class is injected to the base class and provides implementations for certain features that are resolved at compile time.
The base class is inherently intended, to be instantiated exclusively via inheritance. Thus you should ensure not to have any instantiations outside an inheritance context.
To avoid users of your implementation trapped by this misconception, make base's constructor(s) protected:
template <class T>
class base {
public:
~base() {
static_cast<T*>(this)->destroyData();
}
// ...
protected:
T* thisPtr;
base() : thisPtr(static_cast<T*>(this)) {
}
};
NOTE: The base class shouldn't call any methods dependent on the fully initialized derived class methods from within your base class constructor though, as you have shown with your sample (static_cast<T*>(this)->setData();)!
You may store the reference to T* for later use though, as shown in the above sample.
class derived : public base<derived> {
public:
derived() {
setData();
}
void destroyData() {
delete x;
x = nullptr;
}
void print_int() {
std::cout << "x = " << *x << std::endl;
}
private: // ????
derived(const derived& other) {}
inline derived& operator= (derived copy) {}
int *x;
};
Also it's a bit unclear, why you want to hide copy constructor and assignment operator for your class?
tmp is a base<derived>, not a derived. The point of CRTP is that the base class "knows" the object's actual type because it's being passed as the template parameter, but if you manually create a base<derived>, then the base class functions would think the object is a derived, but it isn't - it's just a base<derived>. Weird things (undefined behavior) happen as a result. (As noted in the other answer, you are also printing out something without setting it...)
As to your second question, the checks generated by MSVC to detect those sorts of programmer errors appears to be turned off in Release mode, presumably for performance reasons.
template <class T> class mix_in:public T {
public:
base() { (this)->setData(); }
~base() { (this)->destroyData(); }
void print() { (this)->print_int(); }
};
Rename derived to foo. Do not inherit from mix_in or base in foo.
Swap base for mix_in in main.
CRTP is not the solution to all problems.
You say in comments,
the derived class will never be instantiated, its constructor is never called
Others have already pointed out the undefined use of an unconstructed object. To be specific, consider that int *x is a derived member, and your base<derived> usage generates calls, in sequence, to derived::set_data(), derived::print_int(), and on exit derived::destroy_data(), all member functions of an object that doesn't exist, referring to a member for which you've never allocated space1.
But I think what you're after is wholly legitimate. Factoring code is the whole point of templates and inheritance, i.e. to make important code easier to even identify let alone comprehend, and any later refactoring easier to do, by abstracting out boilerplate.
So:
template < class T >
struct preconstruction_access_subset {}; // often left empty
template < class T, class S = preconstruction_access_subset<T> >
struct base : S {
base() { S::setData(); }
~base() { S::destroyData(); }
void print() { S::print_int(); }
};
// ... later ...
#include <iostream>
struct derived;
template<> struct preconstruction_access_subset<derived> {
// everything structors in `base<derived>` need
int *x;
void setData() { x = new int; }
void destroyData() { delete x; }
void print_int() { std::cout << x << '\n'; }
};
struct derived : base<derived> {
// everything no structors in any base class need to access
};
int main() {
base<derived> tmp;
tmp.print();
}
In this example print_int() isn't actually accessed during construction, so you could drop it back into the derived class and access it from `base as for "normal" CRTP, it's just a matter of what's clearest and best for your actual code.
1 That isn't the only problem, just the only one that's apparent without considering any reliance the compiler itself might need to place on the construction sequence. Think independent-name binding and potential inlining and the ways object identity morphs during {de,con}struction and compiler code factoring for all the potential template/inheritance/member-function/etc. combinations. Don't just hoist the int *x; to solve the current symptom, that would just kick the trouble farther down the road even if yours doesn't get that far yet.
I have these two classes:
class A {
public:
A() { m_ptr = NULL; }
void (*m_ptr)();
void a() { if (m_ptr) m_ptr(); }
};
class B : public A {
public:
B() { m_ptr = b; }
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
And I want to use them like this:
B b;
b.a();
and get the following to be called B::b().
Of course this is not being compiled as B::b is not of type void(*)().
How can I make it work?
UPDATE. To whom who asks "why?" and "what for?".
The class A is a very basic class which has many successors in production code. The class B is 6-th successor and I want to extend A (the most convinient place) to call there one more method (from B) which can be present and may be not in another successors af A and B.
A virtual method with empty body can be employed for that but it is ugly and I want to avoid it. Abstract method even more so (because of existing derived successors code).
I don't want to use external function of type void (*)() to not loose access to internal data of all hierarchy.
You can't make it work as your classes are defined now.
Calling a non-static member function of another class requires an instance of that class. You either need to store a reference to the object that owns the member function when storing the function pointer, or pass a reference to the object when you make the call to A::a.
You also need to declare m_ptr with the type void (B::*)(), which is pointer to member of B that is a function taking no parameters and returning void.
Look at this example:
class A {
public:
A() { m_ptr = nullptr; }
void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object.
void (B::*m_ptr)(); // Pointer to member function of B.
};
class B : public A {
public:
B() { m_ptr = &B::b; } // Adress of qualified function.
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
Now we can call B::b like this:
B b;
b.a(b); // Pass reference to b when calling.
Your use of inheritence in this way is confusing as it implies that the real problem you are trying to solve is to invoka a member of a derived class through the base class. This is usually accomplished using a simple virtual function like this:
class A {
public:
virtual ~A() {}
void a() const { b(); } // Call b.
private:
virtual void b() const {}
};
class B : public A {
public:
virtual void b() const override { // C++11 override specifier (optional).
std::cout << "B::b() is called" << std::endl;
}
};
And used like this:
B b;
b.a(); // B::b is called.
Well, probably not the purpose of this exercise, but you can simply declare static void b() if you want to make it work.
Another option is to declare friend void b(), but then the "B::b() is called" printout would be stating a wrong fact.
I would suggest using CRTP since you want to avoid virtual mechanism. Note, however, your code might require some design changes to accommodate this pattern. But it does provide type safety and has no run-time overhead. Hope it helps.
Code on ideone.com:
#include <iostream>
#include <type_traits>
namespace so {
class B;
template<typename T>
class A {
public:
template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
void foo_A() {
std::cout << "foo_A : ";
static_cast<U *>(this)->foo_B();
}
};
class B: public A<B> {
public:
void foo_B() {
std::cout << "foo_B" << std::endl;
}
};
class C: public A<C> {
public:
void foo_C() {
std::cout << "foo_C" << std::endl;
}
};
} // namespace so
int main() {
so::B b_;
so::C c_;
b_.foo_A();
b_.foo_B();
//c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
c_.foo_C();
return (0);
}
Program output:
foo_A : foo_B
foo_B
foo_C
If you have something like this:
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "into func";
}
};
class C : public B
{
};
int main()
{
C c;
c.func();
return 0;
}
Is func() dynamically dispatched?
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Edit: My code didn't compile? Sorry guys. I'm kinda ill right now. My new code also doesn't compile, but that's part of the question. Also, this question is for me, not the faq.
#include <iostream>
template<typename T> class A
{
public:
void func()
{
T::func();
}
};
class B : public A<B>
{
public:
virtual void func()
{
std::cout << "in B::func()\n";
}
};
class C : public B
{
public:
virtual void func() {
std::cout << "in C::func()\n";
}
};
class D : public A<D> {
void func() {
std::cout << "in D::func()\n";
}
};
class E : public D {
void func() {
std::cout << "in E::func()\n";
}
};
int main()
{
C c;
c.func();
A<B>& ref = c;
ref.func(); // Invokes dynamic lookup, as B declared itself virtual
A<D>* ptr = new E;
ptr->func(); // Calls D::func statically as D did not declare itself virtual
std::cin.get();
return 0;
}
visual studio 2010\projects\temp\temp\main.cpp(8): error C2352: 'B::func' : illegal call of non-static member function
visual studio 2010\projects\temp\temp\main.cpp(15) : see declaration of 'B::func'
visual studio 2010\projects\temp\temp\main.cpp(7) : while compiling class template member function 'void A<T>::func(void)'
with
[
T=B
]
visual studio 2010\projects\temp\temp\main.cpp(13) : see reference to class template instantiation 'A<T>' being compiled
with
[
T=B
]
I'm not sure I understand what you're asking, but it appears you are missing the essential CRTP cast:
template<class T>
struct A {
void func() {
T& self = *static_cast<T*>(this); // CRTP cast
self.func();
}
};
struct V : A<V> { // B for the case of virtual func
virtual void func() {
std::cout << "V::func\n";
}
};
struct NV : A<NV> { // B for the case of non-virtual func
void func() {
std::cout << "NV::func\n";
}
};
If T does not declare its own func, this will be infinite recursion as self.func will find A<T>::func. This is true even if a derived class of T (e.g. DV below) declares its own func but T does not.
Test with different final overrider to show dispatch works as advertised:
struct DV : V {
virtual void func() {
std::cout << "DV::func\n";
}
};
struct DNV : NV {
void func() {
std::cout << "DNV::func\n";
}
};
template<class B>
void call(A<B>& a) {
a.func(); // always calls A<T>::func
}
int main() {
DV dv;
call(dv); // uses virtual dispatch, finds DV::func
DNV dnv;
call(dnv); // no virtual dispatch, finds NV::func
return 0;
}
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
Somewhat contradictory, isn't it? A user of class A may know nothing about B or C. If you have a reference to an A, the only way to know if func() needs dynamic dispatch is to consult the vtable. Since A::func() is not virtual there is no entry for it and thus nowhere to put the information. Once you make it virtual you're consulting the vtable and it's dynamic dispatch.
The only way to get direct function calls (or inlines) would be with non-virtual functions and no indirection through base class pointers.
Edit: I think the idiom for this in Scala would be class C: public B, public A<C> (repeating the trait with the child class) but this does not work in C++ because it makes the members of A<T> ambiguous in C.
In your particular example, there's no need for dynamic dispatch because the type of c is known at compile time. The call to B::func will be hard coded.
If you were calling func through a B*, then you would be calling a virtual function. But in your highly contrived example, that would get you to B::func once again.
It doesn't make much sense to talk about dynamic dispatch from an A* since A is a template class - you can't make a generic A, only one that is bound to a particular subclass.
How could you implement class A such that if B has a virtual override, that it is dynamically dispatched, but statically dispatched if B doesn't?
As others have noticed, it's really hard to make sense of that question, but it made me remember something I have learned a long time ago, so here's a very long shot at answering your question:
template<typename Base> class A : private Base
{
public:
void func()
{
std::count << "A::func";
}
};
Given this, it depends on A's base whether func() is virtual. If Base declares it virtual then it will be virtual in A, too. Otherwise it won't. See this:
class V
{
public:
virtual void func() {}
};
class NV
{
};
class B : public A<V> // makes func() virtual
{
public:
void func()
{
std::count << "B::func";
}
};
class C : public A<NV> // makes func() non-virtual
{
public:
void func()
{
std::count << "C::func";
}
};
Would this happen to answer your question?
Whether the function is dynamically dispatched or not depends on two things:
a) whether the object expression is a reference or pointer type
b) whether the function (to which overload resolution resolves to) is virtual or not.
Coming to your code now:
C c;
c.func(); // object expression is not of pointer/reference type.
// So static binding
A <B> & ref = c;
ref.func(); // object expression is of reference type, but func is
// not virtual. So static binding
A<D>* ptr = new D;
ptr->func(); // object expression is of pointer type, but func is not
// virtual. So static binding
So in short, 'func' is not dynamically dispatched.
Note that :: suppresses virtual function call mechanism.
$10.3/12- "Explicit qualification with
the scope operator (5.1) suppresses
the virtual "call mechanism.
The code in OP2 gives error because the syntax X::Y can be used to invoke 'Y' in the scope of 'X' only if 'Y' is a static member in the scope of 'X'.
Seems you just had to add a little trace and usage to answer your own question...
#include <iostream>
template<typename T> struct A {
void func() {
T::func();
}
};
struct B1 : A<B1> {
virtual void func() {
std::cout << "virtual void B1::func();\n";
}
};
struct B2 : A<B2> {
void func() {
std::cout << "void B2::func();\n";
}
};
struct C1 : B1 { };
struct C2 : B2 { };
struct C1a : B1 {
virtual void func() {
std::cout << "virtual void C1a::func();\n";
}
};
struct C2a : B2 {
virtual void func() {
std::cout << "virtual void C2a::func();\n";
}
};
int main()
{
C1 c1;
c1.func();
C2 c2;
c2.func();
B1* p_B1 = new C1a;
p_B1->func();
B2* p_B2 = new C2a;
p_B2->func();
}
Output:
virtual void B1::func();
void B2::func();
virtual void C1a::func();
void B2::func();
Conclusion: A does take on the virtual-ness of B's func.