Going under the assumption that there is a legitimate reason for preventing derivation from some class, Bjarne gives a solution here for the answer to "Can I stop people deriving from my class?"
However, I thought of:
class final {
protected:
final() { } // line 3
};
class B : private virtual final {
};
class D : public B { // line 9
};
int main() {
B b;
D d; // line 14
}
When trying to compile, one gets:
foo.cpp: In constructor ‘D::D()’:
foo.cpp:3: error: ‘final::final()’ is protected
foo.cpp:9: error: within this context
foo.cpp: In function ‘int main()’:
foo.cpp:14: note: synthesized method ‘D::D()’ first required here
Does my solution work for all cases? IMHO, it's better because the class final is generic and doesn't require foreknowledge of the class to prevent derivation from.
The solution is rather bad, it could be improved with CRTP (adobe does so) but it won't be a complete solution. The problem with your code is that another programmer that does not want to break your contract (she is a good person) but does not know that she should not derive from your class might want to lock others from deriving from her own class:
class YourSealedClass : private virtual final {};
class HerSealedClass : public YourSealedClass, private virtual final {
};
Note that there is not even malign intention, and the contract is broken. The improvement with CRTP would be:
template <typename T>
class seal
{
protected:
seal(){}
~seal(){}
};
class YourSealedClass : private virtual seal<YourSealedClass> {};
This will catch the previous mistake, as her code would be:
class HerSealedClass : public YourSealedClass, private virtual seal<HerSealedClass> {};
And as she is not inheriting from seal<YourSealedClass> the compiler will catch it up.
The problem with this approach is that it does not block some stubborn (or malign) programmer from writing:
class MalignClass : public YourSealedClass, private virtual seal<YourSealedClass> {};
To become a child of the sealing class, and as such gain access to your own class.
In C++0x I believe (would have to recheck it) that they will raise the restriction that a template cannot befriend a template argument, and that will be a good step into a generic typesafe solution for a class sealer:
template <typename T>
class seal {
friend class T; // illegal in C++03
seal() {};
~seal() {};
};
class MySealedClass : private virtual seal<MySealedClass>
{};
The advantage of this approach (currently unavailable) is that because the constructor and destructors are private only friends can instantiate the type. Because you are using the CRTP to inherit from an specific instantiation passing your own type as argument, you are telling the compiler that only you can actually instantiate your base, and all pieces fall right into place.
Try:
class D : public B, public virtual final
{
};
Related
I'm trying to publicly derive a class from a template that will make it inherit from a base class and get access on protected members. But before the template is expanded it doesn't have those rights, so it can't use a Base member as a template parameter:
using Fun = void (*)();
class Base {
protected:
// friend class Derived; // ...need this to eliminate complaint
static void something();
};
template<Fun F>
class Variant : public Base {};
class Derived : public Variant<&Base::something> { // `something()` is protected
public:
void somethingElse() {
something(); // doesn't complain about this `something()`
}
};
int main() {}
The weird bit about this to me was that friending it worked at all. I wondered if I might "sneak Derived in the door" by putting a public virtual inheritance from Base before the Variant:
class Derived : public virtual Base, public Variant<&Base::something>
That didn't help.
Question: is there some other trick for avoiding explicit mention of all derived classes in Base, yet still have access to pick protected members out of it for template parameters?
(Note: Trying this on an older gcc, 4.6.3, looks like even the friending doesn't help in that case. So it seems support for that is somewhat new.)
Stick the offending access into a metafunction. Derive the metafunction class from the base.
template<typename B>
struct something_variant : public B {
typedef Variant< & B::something > type;
};
class Derived : public something_variant<Base>::type {
…
http://coliru.stacked-crooked.com/a/6bca00455bd3daca
Regarding CWG 372, the critical text in the resolution is this:
[A]ccess checking of base-specifiers must be deferred until the entire base-specifier-list has been seen.
This was already accepted in C++11, so it's interesting that your example is rejected. And, plugging the relevant example code from the C++11 standard into recent Clang and GCC demonstrates that they simply did not implement the deferral. It's at least a little unsurprising, since implementation requires some data structure to represent a set of deferred access checks… fairly high effort for a corner case.
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};
I would like to know if there's a way to make a method from a derived class a friend of its base class. Something like:
class Derived;
class Base
{
int i, j;
friend void Derived::f();
protected:
Base();
};
class Derived : public Base
{
public:
void f();
};
The errors I got were:
error: C2027: use of undefined type 'Derived'
see declaration of 'Derived'
error: C2248: 'Base::i' : cannot access private member declared in class 'Base'
see declaration of 'Base::i'
see declaration of 'Base'
error: C2248: 'Base::j' : cannot access private member declared in class 'Base'
see declaration of 'Base::j'
see declaration of 'Base'
error: C2027: use of undefined type 'Derived'
see declaration of 'Derived'
I struggled with it during all the day. Everything I found about friendship use only separated classes, not inheritance.
No there is no direct way : Base needs the definition of Derived::f while Derived also needs the definition of it's Base class.
But it does not matter, you should not do that, you can, in order of preference :
Provide protected accessors in the Base class
Make the entire Derived class a friend (not necessary in general)
You can use an intermediate helper class which only forward the call of this specific method, and give it friendship :
Example here:
class Base;
class Derived;
class Helper final
{
friend class Derived;
public:
void f(Base* base);
private:
Helper() {}
};
class Base
{
int i, j;
friend class Helper;
protected:
Base() {}
};
class Derived : public Base
{
public:
void f();
private:
Helper helper;
};
void Helper::f(Base* base)
{
base->i = 10; base->j = 5;
std::cout << "Help !" ;
}
void Derived::f()
{
helper.f(this);
}
One approach for this kind of problem is to apply the rule "if it's a thing, then it's a class."
#quantdev solution is on those lines.
Based on the comment:
assuming that I have two classes both derived from base class and
having an identical private member. Why not saving some codes by
putting that member in the base class and providing a friend access to
both derived classes that need the member. Assuming that other derived
classes won't be able to access that member at all. That's what I'm
trying to achieve
[I know that this does not answer the specified question, but may be what you need.]
I'd solve that by factoring the common element into an intermediate class:
class Base
{
public:
Base();
virtual ~Base() = 0;
};
class Derived : public Base
{
public:
void f()
{
i = 1;
}
private:
int i, j;
};
class Foo : public Derived
{};
class Bar : public Derived
{};
class Fred : public Base
{};
I don't know if it is possible to do exactly what you want (although it seems to me like it should be) -- and I'd be interested to see other answers that show how if it is -- but there are a few other ways to achieve what you want. I assume you are asking about this situation in general -- that is, you are also interested in the case where there can be many different derived classes, not all of which need, no should have access to the private fields of Base (otherwise you should make these fields protected of course).
First, the easiest thing to do would be to make Derived a friend class to Base, although this feels like a hack (in part because it doesn't allow for any encapsulation of Base with respect to Derived) and is definitely sub-optimal here.
In my opinion, a somewhat better approach in terms of encapsulation would be to make an external "free" (non-member) function that is a friend to Base (and potentially Derived if you need that too). This gets around the circular compiler error, but unfortunately still loses the conceptual semantics of being an "operation on Derived".
Found related questions but not the exact variant so I am posting a very simple question.
A derived class inherits from a templated base, and I want to call the base function, how to do it?
template <class A>
class testBase {
public:
void insert(const A& insertType) {
// whatever
}
};
class testDerived : testBase<double> {
// whatever
};
int main() {
testDerived B;
// Compiler doesn't recognize base class insert
// How do you do this?
B.insert(1.0);
}
Need public inheritance (default is private for class):
class testDerived : public testBase<double> {
A class has a default access level of 'private'. You basically inherited 'testBase' using private inheritance so that testBase's public interface is not part of testDerived's. Simple solution:
class testDerived: public testBase<double> {...};
I do wish C++ applied public inheritance by default though since that's generally a much more common case. Then again, we could just all use structs instead. :-D
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.