I'm trying to do have Derived derive from Base:
class Base
{
public:
Base() {};
};
template <class T>
class Derived : public Base
{
public:
Derived::Derived()
{
}
};
This gives me the following error:
error C3254: 'Derived':
class contains explicit override '{ctor}' but does not derive from an
interface that contains the function declaration
note: see reference to
class template instantiation 'Derived' being compiled
error C3244:
'Derived::Derived(void)': this method was introduced by 'Unknown>'
not by 'Base'
I'm totally new to templates, what simple steps am I missing? This seems like a pretty basic thing.
You need to omit the "Derived::" prefix. You would only use it to refer to a symbol that was inherited, or injected into the namespace of the class Derived. So the only prefix that makes sense is "Base::" here. It has nothing to do with templates.
class Base
{
public:
Base() {};
};
template <class T>
class Derived : public Base
{
public:
Derived() {}
};
See a working Live Demo.
Related
I want to make it so that only one class, Der, can subclass a Base class. So I made the constructor of Base private, and added Der as a friend of Base:
struct Base {
template<class T>
friend struct Der;
private:
Base() = default;
};
template<class T>
struct Der : Base {};
This works great.
However another struct, DerDer, inherits from Der, multiple times with different template arguments.
struct DerDer : Der<int>, Der<char> {};
This is a problem because now there are two Base in the hierarchy, so the solution is to make Der virtually inherit from Base:
template<class T>
struct Der : virtual Base {};
This now breaks, I believe if a class is virtually inherited then the most derived class is responsible for calling the constructor (not really sure why). Which is a problem because DerDer is not a friend of Base and so therefore can not access it's constructor.
How can I fix this?
(It seems like it's an implementation detail that virtual inheritance makes the most derived class call the constructor, and so friending should respect that it's otherwise correct to do this and this is a kind of a bug in the compiler (or standard))
One option is to use a private nested struct to control permission to construct a Base.
struct Base {
template<class T>
friend struct Der;
private:
struct Permission {};
public:
Base(Permission) {}
virtual ~Base() = default;
};
template <class T>
struct Der : public virtual Base {
protected:
using Permission = Base::Permission;
public:
Der() : Base(Permission{}) {}
};
struct DerDer : Der<int>, Der<char> {
DerDer() : Base(Der<int>::Permission{}) {}
};
Now writing constructors is a little awkward, but the only way to construct a Base is to be or inherit Der<T> for some T.
How can I fix this?
The simplest solution is to make Base::Base() a public member function.
Hope this is not duplicated, but wasn't able to find an elegant solution. Is it possible to say that subclasses of a special base class can only created in a template factory function? Because of simplicity I only want to force this behavior in the base class. Here is an simple example:
template <class T>
T* createBase();
template<typename T>
class Base {
protected:
template <class T>
friend T* createBase();
static T* create()
{
return new T();
}
};
class TestClass1 : public Base<TestClass1>
{
public:
TestClass1() : Base() {}
};
template <class T>
T* createBase()
{
static_assert(std::is_base_of<Base<T>, T>::value, "use the createBase function only for Base<T> subclasses");
return Base<T>::create();
}
Actually this is allowed:
TestClass2 *testClass = createBase<TestClass2>();
TestClass2 tester;
But I only want to have this:
TestClass1 *testClass = createBase<TestClass1>(); //allowed
TestClass1 tester; // compile error
For sure I know I only have to put the constructor of TestClass1 private or protected. But it would be really nice to say that in the Base object.
Edit:
An compile error when the constructor of the subclass is public would be a also a nice solution. Maybe with a static_assert().
You can't control the accessibility of a constructor from the base class, even with CRTP.
What you can do is add a static_assert in the base ctor checking that the T a.k.a the derived class has no publicly accessible default ctor:
template <class T>
class Base {
public:
Base() {
static_assert(!std::is_default_constructible<T>::value,
"T must not be default constructible");
}
};
the static_asswert doesn't work on class scope for reasons showned here: CRTP std::is_default_constructible not working as expected
I have the following class structure:
class Base {
public:
std::set<Index> openIndices;
Base() {};
};
template<typename lhs_t, typename rhs_t>
class Derived : public Base {
public:
lhs_t &lhs;
rhs_t &rhs;
Derived(lhs_t &_lhs, rhs_t &_rhs) :
Base(),
lhs(_lhs),
rhs(_rhs),
openIndices(std::set_symmetric_difference(lhs.openIndices, rhs.openIndices))
{
}
};
So basicly a template Class Derivedderived from the base class Base. When accessing the member variables ob the baser class I get the following error:
test.h:34:88: error: class ‘Derived<lhs_t, rhs_t>’ does not have any field named ‘openIndices’
I am aware of this question: I cannot access the member variables in case my class is derived from a template class. But in my case I am not derived from a template class, still I can't access the member variables. Could anyone tell me why?
You cant initialize member variables of a base class. You have to provide an appropriate constructor in the base class and call this constructor.
I am trying to forward declare a class that is derived from a template class that must also be forward declared.
Here is an example of the classes:
class TType {
public:
TType() { }
};
template<typename T>
class Base {
public:
Base() { }
};
class Derived : public Base<TType> {
public:
Derived() { }
};
Here is a failed guess at what I need:
class TType;
template<typename T> class Base;
class Derived : public Base<TType>; // This fails
Derived* pDerived;
Just forward declare the class name:
class Derived;
You can't include any more information about a class in its declaration; base classes, members, etc. can only be declared in the class definition.
This forward declaration can be used to do various things, including declaring pointers or references (such as pDerived in your example), and also declaring functions with Derived as an argument or return type. If you need to do anything that needs to know the class's size, base classes, or members, then you'll need the full definition.
How to stop the class to be inherited by other class.
C++11 solution
In C++11, you can seal a class by using final keyword in the definition as:
class A final //note final keyword is used after the class name
{
//...
};
class B : public A //error - because class A is marked final (sealed).
{ // so A cannot be derived from.
//...
};
To know the other uses of final, see my answer here:
What is the purpose of the "final" keyword in C++11 for functions?
C++03 solution
Bjarne Stroustrup's code : Can I stop people deriving from my class?
class Usable;
class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
class Usable : public virtual Usable_lock {
public:
Usable();
Usable(char*);
};
Usable a;
class DD : public Usable { };
DD dd; // error: DD::DD() cannot access
// Usable_lock::Usable_lock(): private member
Generic_lock
So we can make use of template to make the Usable_lock generic enough to seal any class:
template<class T>
class Generic_lock
{
friend T;
Generic_lock() {} //private
Generic_lock(const Generic_lock&) {} //private
};
class Usable : public virtual Generic_lock<Usable>
{
public:
Usable() {}
};
Usable a; //Okay
class DD : public Usable { };
DD dd; //Not okay!
There are two ways, the simple cheap, and the correct one. The two answers by #Naveen and #Nawaz deal with the correct one, that requires manual creation of a sealer class for each class that you actually want to seal.
The not fool-proof way, which is used in the adobe libraries is using a templated class for that. The problem is that you cannot declare the template argument as a friend, and that means that you will have to switch from private to the less safe protected:
template <typename T>
class sealer {
protected: sealer() {}
};
class sealed : virtual sealer<sealed> {};
And you can automate it with a macro (I don't remember the exact flavor of the macro in Adobe's code):
#define seal( x ) virtual sealer<x>
class sealed : seal(sealed)
{};
Now this will catch people that mistakenly try to inherit without knowing that they shouldn't:
class derived : sealed {};
int main() {
derived d; // sealer<T>::sealer() is protected within this context
}
But it will not inhibit people that really want to from deriving, as they can gain access to the constructor by deriving from the template themselves:
class derived : sealed, sealer<sealed> {};
int main() {
derived d;
};
I am not sure whether this will change in C++0x, I think I recall some discussions on whether a class template would be allowed to befriend one of it's arguments, but in a cursory search through the draft I cannot really tell. If that was allowed then this would be a fine generic solution:
template <typename T>
class sealer {
sealer() {}
friend class T; // Incorrect in C++03
};
C++11 adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:
class Base final { };
class Derived1 : Base { }; // ill-formed because the class Base has been marked final
or
class Base {
virtual void f() final;
};
class Derived : Base {
void f(); // ill-formed because the virtual function Base::f has been marked final
Note that final is not a language keyword. It is technically an identifier; it only gains special meaning when used in those specific contexts. In any other location, it can be a valid identifier.
Based on Bjarne Stroustrup's http://www.stroustrup.com/bs_faq2.html#no-derivation FAQ
with small modification without friend keyword usage:
// SEALED CLASS DEFINITIONS
class Usable_lock {
protected:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
#define sealed_class private virtual Usable_lock
// SEALED CLASS USAGE EXMAPLES
class UsableLast : sealed_class {
public:
UsableLast(){}
UsableLast(char*){}
};
class DD : public UsableLast {};
// TEST CODE
template <class T> T createInstance() {
return T();
}
int main()
{
createInstance<UsableLast>();
// createInstance<DD>();
return 0;
}
The following code shows how to define a sealed class in C++/CLI.
class A sealed
{
//here goes the class code
};
class B : public A
{
};
Now B : cannot inherit from A as it has been declared as 'sealed'. Also a detailed explanation about sealed keyword can be found here http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx
Update: Added C++/CLI , also other answers have shown the latest C++11 way of achieving the same using final keyword.
You cannot. C++ is not Java or C#. And also there is no point, ever, IMHO.