I have a class that looks something like this:
class A
{
public:
void foo(int arg) { foo(arg, false); }
private:
void foo(int arg, bool flag) {}
};
It is built this way because I want foo's flag argument to only be false when called from outside A. I want to inherit it privately, but allow calling foo:
class B : private A
{
public:
using A::foo;
};
However, this fails because the using declaraion attempts to bring all the overloads of foo into scope, including the private one, which the the compiler rightly rejects.
This isn't hard to fix, I can either:
Change the accessibility of A::foo(int, bool) to protected or public
Inherit A publicly; only public overloads of foo will be inherited
Change the name of A::foo(int, bool) so that the using declaration does not attempt to bring it into scope
This is a small, private project, and besides, that overload is only called inside A. So fixing the problem is a non-issue here. (I'm just going to rename the private overload.)
But it doesn't feel like it should be necessary. Why does the using declaration attempt to bring the non-accessible methods into scope? Is this particular case just not covered by the standard? Is there a way to fix this besides the methods I listed?
You can also redefine the overload you want and have it forward its argument to the function in A:
class B : private A
{
public:
void foo(int arg) { A::foo(arg); }
};
The using declaration is just too blunt a tool in this case. It brings function names into the derived class scope. And when the name refers to something private, it chokes. It can't distinguish overloads. The standard requires the names introduced by a using declaration to be accessible:
[namespace.udecl]/17
In a using-declarator that does not name a constructor, all members of
the set of introduced declarations shall be accessible. In a
using-declarator that names a constructor, no access check is
performed. In particular, if a derived class uses a using-declarator
to access a member of a base class, the member name shall be
accessible. If the name is that of an overloaded member function, then
all functions named shall be accessible. The base class members
mentioned by a using-declarator shall be visible in the scope of at
least one of the direct base classes of the class where the
using-declarator is specified.
The forwarding function can also be templated. So one won't need to redefine each function they want to expose individually.
class B : private A
{
public:
template<typename ...Args>
void foo(Args ...args) { A::foo(args...); }
};
It's "catch-all" like the using declaration, except the access specifier is checked only on template instantiation, i.e. when the function is called. So the template will be ill-formed based on its scope and whether or not the member in A is accessible there.
I found the following extract from Scott Meyer's Effective C++ which is related to your predicament (with emphasis added):
Item 33: Avoid hiding inherited names.
...
This means that if you inherit from a base class with overloaded functions
and you want to redefine or override only some of them, you need
to include a using declaration for each name you’d otherwise be hiding.
If you don’t, some of the names you’d like to inherit will be hidden.
...
It’s conceivable that you sometimes won’t want to inherit all the functions
from your base classes. Under public inheritance, this should
never be the case, because, again, it violates public inheritance’s is-a
relationship between base and derived classes. (That’s why the using
declarations above are in the public part of the derived class: names
that are public in a base class should also be public in a publicly
derived class.)
Under private inheritance, however, it can
make sense. For example, suppose Derived privately inherits from
Base, and the only version of the function that Derived wants to inherit is the
one taking no parameters. A using declaration won’t do the trick here,
because a using declaration makes all inherited functions with a given
name visible in the derived class.
No, this is a case for a different technique, namely, a simple forwarding function:
class Base {
public:
virtual void mf1() = 0;
virtual void mf1(int);
... // as before
};
class Derived: private Base {
public:
virtual void mf1() // forwarding function; implicitly
{
Base::mf1(); } // inline
};
}
Related
using namespace std;
#include <cstdio>
#include <iostream>
class One{
private:
virtual void func(){
cout<<"bark!"<<endl;
}
};
class Two: public One{
public:
void func(){
cout<<"two!"<<endl;
}
};
int main(){
One *o = new Two();
o->func();
}
Why is there an error on o->func()?
I don't know the mechanism behind it... In my opinion, o->func() should call the func() in the derived class, which is public, so there wouldn't be problems, but it says:
error: ‘virtual void One::func()’ is private
Accessibility check is performed based on the static type of the object. The type of o is One*. This means that if One::func() is private, then o->func() won't compile.
On the other hand, which virtual member function will be called (i.e. dynamic dispatch) happens at run-time, based on the dynamic type of the object. So if One::func() is public, o->func() will call Two::func(), because o is pointing to an object of type Two.
For your sample code and use case, making One::func() private is just meaningless. But note that there's a famous idiom called Non-Virtual Interface, which makes use of private virtual member functions of base class.
Other suggestions:
Don't forget to delete o;
Add a virtual destructor in the base class One. Otherwise delete o; will lead to undefined behavior; e.g. the destructor of Two might not be invoked.
class One {
public:
virtual ~One() {}
// ...
};
A subclass can't ease inheritance restriction,
even though func is virtual, it is still the inheritance restrictions remain.
please see this answer for compliated view of inheritance restrictions :
Difference between private, public, and protected inheritance
Please check Access specifiers and virtual functions.
From standard :
§11.5 [class.access.virt] The access rules (Clause 11) for a virtual
function are determined by its declaration and are not affected by the
rules for a function that later overrides it.
Access is checked at the call point using the type of the expression
used to denote the object for which the member function is called. The
access of the member function in the class in which it was defined is
in general not known.
If name lookup determines a viable function to be a virtual function, the access specifier of the virtual function is checked in the scope of the static type of the object expression used to name the function. At run time, the actual function to be called could be defined in the derived class with a completely different access specifier. This is because 'access specifiers' are a compile time phenomenon.
Since access specifier of function func() is checked in the scope of One *o, and it is private in class One, it produces error.
If Onedeclares func() as public, and Two declares it private, there won't be any errors. See this Private function invoked and it works. Could any of you reason it please
Unfortunately, I studied class design and design patterns mostly in the context of Java; thus, I sometimes have a hard time to translate a familiar pattern to C++.
Assume we want to have a base class which's functionality is extended by a sub-class. In Java, we would do something like this:
public class BaseClass<T> {
//T is used here
protected int foo = 0;
}
public class DerivedClass<T> extends BaseClass<T> {
public void incr_foo() {
++foo;
}
}
Which I directly translated to C++:
template<class T>
class BaseClass {
protected:
size_t foo = 0;
//T is used here
};
template<class T>
class DerivedClass : public BaseClass<T> {
public:
void incr_foo() {
++(this->foo);
}
};
Since the C++ semantics of 'protected' diver from the Java-semantics, we need to use something like 'this->foo' to access protected members of the base class.
Edit: If we just use '++foo', the compiler gives the error: 'use of undeclared identifier foo'.
EditEnd
If you need to access several members of the base class, this can get a bit tedious and is not so nice to read.
Is this a good design desicion? If not, what better ways are there to achieve this?
This has nothing to do with the member being protected; you'd get the exact same error with a public member.
The real reason is that templates are involed. More specifically, that your class template has a base class which depends on a template parameter. This means that when parsing the template, the compiler will not (be able to) look into that base class to find inherited members which are used unqualified. It makes sense: when the template is parsed, the template parameter values are not known yet and thus the compiler has no idea what members the base class will have (remember partial and total specialisation exist!).
In order to overcome this, you must somehow tell the compiler that the name foo depends on template parameters (that it's a dependent name). Once you do so, the compiler will not try to resolve it when parsing the template; it will postpone resolution until the template is instantiated. At that point, template arguments are known and thus the base class can be checked.
You have three ways to mark a member name as dependent:
Refer to the name through this, as you're doing: this->foo
Refer to the name through base-class qualification: BaseClass<T>::foo
Bring the name into the scope of the derived class:
template<class T>
class DerivedClass : public BaseClass<T> {
protected:
using BaseClass<T>::foo; // from this point on, `foo` is a dependent name
public:
void incr_foo() {
++foo; // works fine now
}
};
BaseClass<T> is a dependent type - it depends on the template parameter used to instantiate DerivedClass. Until DerivedClass instantiated, the compiler doesn't know what the type is: it might be an instantiation of the generic template, or it might be an explicit specialisation, with different members.
So, within the definition of DerivedClass, there is no way to know which names refer to members of the base class. You have to specify that they are, using this-> or BaseClass::.
In a class with a non-dependent base class, you can use any accessible base-class members as if they were direct members, just as in Java.
Consider following example
#include <iostream>
struct PureVirtual {
virtual void Function() = 0;
};
struct FunctionImpl {
virtual void Function() {
std::cout << "FunctionImpl::Function()" << std::endl;
}
};
struct NonPureVirtual : public FunctionImpl, public PureVirtual {
using FunctionImpl::Function;
};
int main() {
NonPureVirtual c;
c.Function();
}
Compiler (GCC 4.9, Clang 3.5) exits with error
test.cpp:18:20: error: variable type 'NonPureVirtual' is an abstract class
NonPureVirtual c;
^
test.cpp:4:18: note: unimplemented pure virtual method 'Function' in 'NonPureVirtual'
virtual void Function() = 0;
^
But when I don't derive form PureVirtual everything is OK. This is weird because Standard 10.4.4 says
A class is abstract if it contains or inherits at least one pure
virtual function for which the final overrider is pure virtual.
They are not saying anything about what the final overrider is but I suppose it should be FunctionImpl::Function() especially when I made it available through using directive. So why is still NonPureVirtual abstract class and how can I fix this.
FunctionImpl::Function and PureVirtual::Function are different functions from different classes.
Their respective types are void (FunctionImpl::*)() and void (PureVirtual::*)().
Since PureVirtual and FunctionImpl are unrelated classes, these function types are unrelated.
They happen to have the same name and the same parameters and return type, but since they're different, the using FunctionImpl::Function line doesn't make that function an override of the one in PureVirtual.
And if you declared a variable of type void (PureVirtual::*)(), you wouldn't be able to assign FunctionImpl::Function to it.
In other words, the final override of PureVirtual::Function is the original one in PureVirtual, which is pure virtual.
For making what you want possible, Matthieu M.'s answer (using a forwarding call) is the way to go, it seems.
You cannot use a using directive and have to resort to a fowarding call instead:
struct NonPureVirtual : public FunctionImpl, public PureVirtual {
virtual void Function() override {
return FunctionImpl::Function();
}
};
And yes, it works as expected.
You're attributing a using declaration with something that it doesn't do. What it does is (From draft n3337, 7.3.3/1):
... using-declaration introduces a name into the declarative region in which the using-declaration appears.
Later from the same paragraph:
If a using-declaration names a constructor (3.4.3.1), it implicitly declares a set of constructors in the
class in which the using-declaration appears (12.9); otherwise the name specified in a using-declaration is a
synonym for the name of some entity declared elsewhere.
In your case, FunctionImpl::Function is first declared in FunctionImpl class and it is its member. A using-declaration doesn't change that fact, as paragraph 16 says further down:
For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function, and in all other respects the function remains a member of
the base class.
Now on to the definition of overriding (10.3/2):
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf. For convenience we say that any virtual function overrides itself.
And there's also the definition of a final overrider in the same paragraph.
A virtual member function C::vf of a class object S is a final overrider unless the most derived class (1.8) of which S is a base class subobject (if any) declares or inherits another member function that overrides vf. In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed. [...]
I think that makes it clear that you can't use a using declaration to override a virtual function. A possible fix is in Matthieu's answer.
Given that we have overloaded methods in base class, and a derived class that was inherited as private/protected.
Can we restore only one/several of the original access level of the overloaded methods?
On GCC 4.4.0 i try to put the base methods under protected access, then inherited it using private access. When i try to restore the access level to public, it works! Is this how its suppose to work? or is it a bug on the compiler? To my understanding, restoring access level shouldn't be able to be used to promote or demote a member's access level.
Code snippet :
class base {
public:
void method() {}
void method(int x) {}
protected:
void method2() {}
};
class derived : private base {
public:
base::method; // Here, i want to restore only the none parameterized method
base::method2; // method2 is now public??
};
Changing accessibility of inherited functions through a using declaration cannot be done selectively on given overload for the simple reason that a using declaration only introduces a name into the declarative region and that by definition, functions overloads share the same name.
The only alternative I see here is to use trivial forwarding functions :
class derived : private base
{
public:
void method() { base::method(); }
using base::method2; // method2 is now public
// method(int) stays inaccessible
};
I'm not quite sure I understand your second question, but yes : you can change base members accessibility in a derived class through using declarations.
You don't restore access, per se. You set access. As you are doing above, you can explicitly set the access for any method, including ones previously declared as private.
It would be impossible to prevent protected methods from being public if the derived class wanted it so, as you could just write a minor wrapper and done. private is another matter.
What are the rules for accessibility when virtual functions are declared under 3 different access specifiers specified by C++(public, private, protected)
What is the significance of each? Any simple code examples to explain the concept will be highly useful.
Access specifiers apply in the same way as they would to any other name during name lookup. The fact that the function is virtual does not matter at all.
There is a common mistake which sometimes happens with respect to virtual functions.
If name lookup determines a viable function to be a virtual function, the access specifier of the virtual function is checked in the scope of the static type of the object expression used to name the function. At run time, the actual function to be called could be defined in the derived class with a completely different access specifier. This is because 'access specifiers' are a compile time phenomonon.
// Brain compiled code ahead
struct A{
virtual void f() {}
private:
virtual void g() {}
protected:
virtual void h() {}
};
struct B : A{
private:
virtual void f() {} // Allowed, but not a good habit I guess!
};
B b;
A &ra = b;
ra.f(); // name lookup of 'f' is done in 'A' and found to be public. Compilation
// succeeds and the call is dynamically bound
// At run time the actual function to be called is 'B::f' which could be private, protected etc but that does not matter
Virtual functions are just like regular functions (exception of pure virtuals) when they are used in the base class.
To summarise from the top of my head:
public functions can be accessed by anyone.
private functions can be accessed only be the class and its friends
protected functions are like private ones, only they can be accessed by derived classes.
Public is the interface, and private/protected functions are the internals.
Also note that all the local variables (according to encapsulism) should be protected/private.
Now, when it comes to derived classes, you derive a class like this:
class A : [public | protected | private] B
{
};
Now, the public/private/protected qualifier infront of B states the least restrictive security level to inherit from the base class. This is not a "filter" for the methods and local variables in the sense that some aren't inherited, it just changes their security level to the one specified if they are less restricted (more public).
So class A : public B will leave the inherited base members as they are while,
class A : private B will change them all to private members.
Hope this makes sense to you and answers your question. If not, tell me!