I have code which uses this design, simplifed to get this MCVE - code and compiler errors follow.
The basic problem is that I thought befriending the CRTP class would allow the templated base class access to the derived CRTP class's private members, including its private constructor.
But apparently it doesn't. Why?
this code on wandbox:
#include <iostream>
using namespace std;
template <class CRTP>
class Base
{
friend CRTP;
public:
static void Factory()
{
cout << "Base::Factory()" << endl;
CRTP x;
x.Hello();
}
virtual void Hello() { cout << "Base::Hello()" << endl; }
protected:
Base() { cout << "Base::Base()" << endl; }
virtual ~Base() { cout << "Base::~Base()" << endl; }
};
class Derived final : public Base<Derived>
{
public:
void Hello() override;
private:
Derived() { cout << "Derived::Derived()" << endl; }
~Derived() override { cout << "Derived::~Derived()" << endl; }
};
int main()
{
Derived::Factory();
// Expected output:
// Base::Factory()
// Base::Base()
// Derived::Derived()
// Derived::Hello()
// Derived::~Derived()
// Base::~Base()
}
And getting this compiler error (from clang 9.0.0, but gcc complains the same way):
prog.cc:12:12: error: calling a private constructor of class 'Derived'
CRTP x;
^
prog.cc:33:14: note: in instantiation of member function 'Base<Derived>::Factory' requested here
Derived::Factory();
^
prog.cc:27:3: note: declared private here
Derived() { cout << "Derived::Derived()" << endl; }
^
prog.cc:12:12: error: variable of type 'Derived' has private destructor
CRTP x;
^
prog.cc:28:11: note: declared private here
virtual ~Derived() { cout << "Derived::~Derived()" << endl; }
^
2 errors generated.
(FYI: Use case is I want the template base class to control lifetime - including construction - of the (CRTP) derived class instances via a static factory. So I want the derived classes to declare their constructors private, yet accessible to the parent's static factory method. This example shows the derived class instance created on the stack but the same errors occur if it is created in the heap (and returned).)
You've got the friend declaration in the wrong class. Derived needs to declare Base<Derived> as a friend, since a friend can access the private members. (A class declares another class to be a friend. A class does not declare itself as a friend of another class.)
You want to add
friend Base<Derived>;
into the Derived class declaration.
The concrete problem you are mentioning is that you placed the friend declaration in Base rather than in Derived.
The next problem is that Derived::Hello() has no implementation. If you don't need one (as in your example above) implement it only in Base and remove the virtual declaration. Derived will inherit it anyways.
The following works:
#include <iostream>
using namespace std;
template <class CRTP>
class Base
{
public:
static void Factory()
{
cout << "Base::Factory()" << endl;
CRTP x;
x.Hello();
}
void Hello() { cout << "Base::Hello()" << endl; }
protected:
Base() { cout << "Base::Base()" << endl; }
virtual ~Base() { cout << "Base::~Base()" << endl; }
};
class Derived final : public Base<Derived>
{
friend Base<Derived>;
/*^^^^^^ friend declaration goes here, not in Base */
Derived() { cout << "Derived::Derived()" << endl; }
~Derived() override { cout << "Derived::~Derived()" << endl; }
};
Output:
Base::Factory()
Base::Base()
Derived::Derived()
Base::Hello()
Derived::~Derived()
Base::~Base()
Related
#include <iostream>
#include <memory>
using namespace std;
class Base
{
public:
virtual void foo() = 0;
protected:
int num{ 1 };
public:
Base() {
cout << "Base class constructor" << endl;
}
virtual ~Base()
{
cout << "Base class destructor " << endl;
}
private:
};
class Derive : public Base {
public:
Derive() {
cout << "Derive class constructor" << endl;
}
~Derive() {
cout << "Derive class destructor " << endl;
}
public:
void foo() override{
cout << "Derive class Foo function" << endl;
}
};
int main() {
unique_ptr<Base> b = make_unique<Base>(new Derive());
b->foo();
}
I get below error when I build this code.
in instantiation of function template specialization 'std::make_unique<Base, Derive *>' requested here unique_ptr b = make_unique(new Derive());
unimplemented pure virtual method 'foo' in 'Base' virtual void foo() = 0;
Does anyone know what is the reason of this error?
Note: I tried on https://godbolt.org/ and selected clang 11
In your main() function, do this instead:
unique_ptr<Base> b(new Derive());
This is because std::make_unique() takes the actual constructor arguments. You can't do that with polymorphism, but there's nothing wrong with directly instanstiating a std::unique_ptr directly with a heap allocated resource.
Do prefer std::make_unique() where it makes sense, though. This just isn't one of those cases.
I'm a newbie in C++ and have a question. I can't find any related stuff for this question on Google.
Is it possible in C++ for code in a virtual function to be called from the base class without invoking it with Base::func() in the derived class?
Here is an example of what I mean:
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void) { cout << "Derived func()" << endl; }
};
The output should be the following when the function func is called from Derived:
Base func()
Derived func()
Is this even possible in C++? Or, is there another way to implement this behavior?
Is that intention even possible in C++? Or is there a other way to implement this behavior in C++?
You can get that behavior only if you add
Base::func();
in the implementation of Derived::func(). The language does not provide a mechanism to make that automatic.
You can make the base class get the calls first by making the interface non-virtual, and then call the (private) derived function from there:
class Base {
public:
void func()
{
cout << "Base func()" << endl;
derived_func();
}
private:
virtual void derived_func() { }
};
class Derived : Base {
private:
virtual void derived_func() { cout << "Derived func()" << endl; }
};
You have call the base class in derived class implementation to make that happen
class Base {
public:
virtual void func(void) { cout << "Base func()" << endl; }
};
class Derived : Base {
public:
virtual void func(void)
{
Base::function();
cout << "Derived func()" << endl;
}
};
But this is still calling Base::func() from Derived::func()
You can, however, achieve what you want if the func() was actually your constructor.
I have an pure virtual base class and a derived class. I know I am allowed to implement a virtual (not pure) method in the base class.
What I do not understand is why I HAVE to also implement the same method in the derived class if what I want is simply to use the base implementation:
#include <iostream>
using namespace std;
class Abstract {
public:
int x;
Abstract(){
cout << "Abstract constructor" << endl;
x = 1;
}
virtual void foo() = 0;
virtual void bar(){
cout << "Abstract::bar" << endl;
}
};
class Derived : Abstract {
public:
int y;
Derived(int _y):Abstract(){
cout << "Derived constructor" << endl;
}
virtual void foo(){
cout << "Derived::foo" << endl;
}
virtual void bar(){
Abstract::bar();
}
};
int main()
{
cout << "Hello World" << endl;
Derived derived(2);
derived.foo();
derived.bar(); //HERE I HAVE TO DEFINE Derived::bar to use it
return 0;
}
You don’t have to do that. You can do the following:
class Derived : public Abstract {
That way, you can use the public methods from the base class.
I'm trying to create a factory for derived classes. I only want the factory to be able to create instances of the derived classes so I've made the base constructor protected; the derived classes just use the base class constructors so their constructors are protected also.
I tried to declare the factory as a friend of the base class so that it could access the protected constructor. When I compile using this command
clang++ -std=c++11 -stdlib=libc++ Friends.cpp -o Friends
I get this error:
Friends.cpp:23:20: error: calling a protected constructor of class 'A'
return new T(i);
^
Friends.cpp:42:16: note: in instantiation of function template specialization 'Create<A>' requested
here
A* a = Create<A>(1);
^
Friends.cpp:30:25: note: declared protected here
using Base::Base;
^
Along with a similar error for derived class B.
I get the feeling from reading other questions on stackoverflow.com, that this isn't possible in C++11, but I'm not sure why. Can someone explain why this won't work and perhaps an alternative?
Example code
#include <iostream>
using namespace std;
// Forward declaration
template<class T> T* Create(int i);
class Base {
public:
template<class T>
friend T* Create(int);
virtual void say() = 0;
protected:
Base(int i): i(i) { } // This won't compile
int i;
};
// Factory for Base class
template<class T>
T* Create(int i){
return new T(i);
}
class A: public Base {
public:
using Base::Base;
void say() { cout << "I am A and have a value of " << i << endl; }
};
class B: public Base{
public:
using Base::Base;
void say() { cout << "I am B and have a value of " << i << endl; }
};
int main(){
cout << "I'm creating A." << endl;
A* a = Create<A>(1);
a->say();
cout << "I'm creating B." << endl;
B* b = Create<B>(2);
b->say();
return 0;
}
When you inherit a constructor from a base class it retains the access of the original constructor, regardless of where you place the using declaration in the derived class.
From §12.9/4 [class.inhctor]
A constructor so declared has the same access as the corresponding constructor in X. ...
You can fix the error if you explicitly add constructors to derived classes instead of inheriting them from Base.
A(int i) : Base(i) {}
and
B(int i) : Base(i) {}
Live demo
Another solution, of course, is to make Base's constructor public. You could also make its destructor protected, but it's not necessary since the class cannot be instantiated anyway due to the pure virtual member function.
class Base {
public:
template<class T>
friend T* Create(int);
virtual void say() = 0;
Base(int i): i(i) { } // This won't compile
int i;
protected:
~Base() {}
};
Live demo
Friendship does not go down the inheritance tree. Create is friend of Base, and therefore can not access the protected A::A(int) and B::B(int).
Possible solutions include:
Make new friendships (A, B and further child classes should be friends of Create)
Use public constructors as mentioned by #Snps
Use an external class that only Base (and therefore also its friend, Create) can create and the rest can only copy. Idea from here.
Code for last solution:
#include <iostream>
using namespace std;
// Forward declaration
template<class T> T* Create(int i);
class Base {
class AccessKey {
friend class Base;
AccessKey() {};
public:
AccessKey(const AccessKey& o) {}
};
static AccessKey getAccessKey() { return AccessKey(); }
public:
template<class T>
friend T* Create(int);
virtual void say() = 0;
Base(int i, AccessKey k): i(i) { } // This can be public as it can be called without and AccessKey object
protected:
int i;
};
// Factory for Base class
template<class T>
T* Create(int i){
return new T(i, Base::getAccessKey());
}
class A: public Base {
public:
using Base::Base;
void say() { cout << "I am A and have a value of " << i << endl; }
};
class B: public Base{
public:
using Base::Base;
void say() { cout << "I am B and have a value of " << i << endl; }
};
int main(){
cout << "I'm creating A." << endl;
A* a = Create<A>(1);
a->say();
cout << "I'm creating B." << endl;
B* b = Create<B>(2);
b->say();
return 0;
}
I would be tempted to make the Create() function a static member of Base and then just make all the derived classes friends of Base:
Run This
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {}
// Factory for Base class
template<class T>
static T* Create(int i) {
static_assert(std::is_base_of<Base, T>::value, "Needs to be derived from Base");
return new T(i);
}
virtual void say() = 0;
protected:
Base(int i): i(i) { }
int i;
};
class A: public Base {
friend Base; // Allow Base to construct
public:
using Base::Base;
void say() { cout << "I am A and have a value of " << i << endl; }
};
class B: public Base {
friend Base; // Allow Base to construct
public:
using Base::Base;
void say() { cout << "I am B and have a value of " << i << endl; }
};
int main(){
cout << "I'm creating A." << endl;
A* a = Base::Create<A>(1);
a->say();
cout << "I'm creating B." << endl;
B* b = Base::Create<B>(2);
b->say();
return 0;
}
EDIT: Added static_assert
EDIT: Added link to run code
I'm attempting to call a method from a base class with the same name as a method in the derived class. Here's a simplified example:
#include <iostream>
using namespace std;
class Base
{
public:
void print() {
cout << "Printing from base" << endl;
}
void print(int num) {
cout << "Printing number from base: " << num << endl;
}
};
class Derived : public Base
{
using Base::print;
public:
void print() {
cout << "Printing from derived" << endl;
}
};
int main()
{
Derived x;
x.print();
x.Base::print(1);
//x.print(1); // Gives a compilation error
return 0;
}
Basically, I'd like to be able to call x.print(1) and get "Printing number from base: 1", that is, automatically call the method which matches the signature, even though it resides in the base class.
Without the using Base::print;, I get error: no matching function for call to 'Derived::print(int)', which makes perfect sense due to name hiding.
Thus, I added that line, but now the error is error: 'void Base::print(int)' is inaccessible
Why is this the case? I use public inheritance, so I would have thought it was readily available?
As demonstrated in the example, it works fine to manually call x.Base::print(1);, but I would like to do it more transparently. Then of course I can re-implement a wrapper to the function in the derived class, but that does not seem very elegant either.
I apologize if this has been covered in an earlier question, I read a bunch of them and found a lot of similar cases, but nothing that helped me.
The placement of the using directive decides about the visibility. Simply place it into the public area and you should be fine:
//...
class Derived : public Base
{
public:
using Base::print;
void print() {
cout << "Printing from base" << endl;
}
};
//...
http://ideone.com/06NNk
You can make your functions virtual. Any virtual functions inherited from the base class that aren't overloaded will be called through the derived class.
class base
{
public:
virtual void Foo() {}
}
class Derived
{
}
Derived d;
d.foo(); // calls base::foo()