Due to the layout of a third-party library, I have something like the following code:
struct Base
{
static void SomeStaticMethod(){}
};
struct Derived1: private Base {};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Base::SomeStaticMethod();
}
};
int main() {
Derived2 d2;
d2.SomeInstanceMethod();
return 0;
}
I'm getting compiler error C2247 with MSVC:
Base::SomeStaticMethod not accessible because Derived1 uses private to inherit from Base.
I know I can't access Base members from Derived2 via inheritance because of the private specifier, but I should still be able to call a static method of Base - regardless of any inheritance relationship between Base and Derived2.
How do I resolve the ambiguity and tell the compiler I'm just making a call to a static method?
Do this:
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
::Base::SomeStaticMethod();
// ^^
// Notice leading :: for accessing root namespace.
}
};
I think michalsrb's answer is better, but for completeness:
namespace
{
void SomeStaticMethodProxy()
{
return Base::SomeStaticMethod();
}
}
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
SomeStaticMethodProxy();
}
};
will also work.
Other answers provide way to solve the problem, I'll try to explain what's happening. It's because of injected-class-name.
9.2 (N4594)
[...]The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name.[...]
Note that even if you type Base::SomeStaticMethod(), obviously SomeStaticMethod is looked up in Base scope (It's qualified name), but name Base itself also has to be looked up somehow, (In this example as an unqualified name (because it does not appear after scope resolution operator))
What happens is that when you search for (unqalified) name Base in Derived2, first Derived2 scope is searched, then Derived1 scope is searched and then Base scope is searched and finally injected-class-name is found. Then access control takes place (because access control takes place after name lookup) and it'll find that name you looked up is Base's member which isn't accessible from Derived2.
You can do this if you want to call it through the hierarchy:
struct Derived1: private Base {
protected:
using Base::SomeStaticMethod;
};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Derived1::SomeStaticMethod();
}
};
Otherwise, do as #michalsrb mentioned if you want to call it directly on Base.
A couple of possibilities:
Don't use the inheritance structure to call the method. Use ::Base::SomeStaticMethod() to call it. Base is accessible in the global namespace.
Bring the private function into the namespace of Derived1 by writing using Base::SomeStaticMethod;
Related
Generally, we wish to use private inheritance to hide the implementation details to the base class. If this is true,
1) Why is the name publicizing feature is there again ? Is it only for language completeness or is there any practical usage also?
2) Even though I publicize the base class function name, a derived class can still declare another function with same name. Please consider the following code.
#include "iostream"
using namespace std;
class Base {
public:
int zoo;
Base() {zoo =5;}
int sleep() const {return 3;}
};
class Derived : Base { // Private inheritance
public:
using Base::zoo;
using Base::sleep;
int sleep() const { return 4.0; }
};
int main() {
Derived der;
der.sleep();
cout<<" zoo is : "<<der.zoo<<endl;
cout<<" Sleep is : "<<der.sleep()<<endl;
}
In the above snippet, even though we publicize the name, we can still declare the name in derived class, and we can access the base class version of member variables. How the memory is managed?
Thank you.
http://en.cppreference.com/w/cpp/language/using_declaration
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.
That link has specific examples of exactly what you are doing an re-iterates what I quoted above and how the base member is simply hidden by the derived member.
When compiling the following example in msvc, I get
'Interface' not accessible because 'Base' uses 'private' to
inherit from 'Interface'
in the line marked with Error. When the call to foo is qualified with a type alias of the same type, it works. I tested with msvc and ideone.
Why are the two calls not equal?
struct Interface {};
template<class T>
struct Base : private T
{
void foo() {}
};
using BaseX = Base<Interface>;
class Derived : Base<Interface>
{
Derived() {
Base<Interface>::foo(); // Error
BaseX::foo(); // Works
}
};
Ideone
Injected-class-names.
The name Interface is injected into the scope of the class Interface as if it's a public member, and in turn inherited by Base<Interface> (as a private member, since you are using private inheritance).
When you write Base<Interface>::foo() in Derived, unqualified name lookup for Interface looks first at Derived and its base class, finds Interface in the base class, and then access control kicks in because that name is private.
The simplest fix is to just write Base::foo(), or even just foo() if it isn't virtual and you aren't planning to write a foo() in Derived.
If you have to include the template argument for some reason, then write Base<::Interface>.
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".
I have a base class:
class Base
{
public:
functions...
private:
std::vector<float> privateElement;
}
and a derived one:
class Derived : public Base
{
public:
functions...
Derived(anotherElement) : privateElement(anotherElement)
{
}
}
My problem now is that everytime I try to build my project, the compiler (gcc 4.7.2) always complains about not being able to access privateElement, like:
class Derived does not have any field named privateElement
std::vector<float> Base::privateElement is private
May anybody help me here?
First of all, private members of base class are not accessible from derived class.
Now even if you fix that and make it protected (or public), then this will still be ill-formed, because you cannot initialize the base's members in the derived class's mem-init-list. It doesn't make sense, because by the time the derived class mem-init-list executes the base's members are already initialized, and the syntax : protectedElement(xyz) will make the compiler think that protectedElement is a member of the derived class, not of the base class!
See this error even after making it protected:
main.cpp: In constructor ‘Derived::Derived(std::vector<float>)’:
main.cpp:20:37: error: class ‘Derived’ does not have any field named ‘protectedElement’
Derived(std::vector<float> v) : protectedElement(v)
^
Online demo
The right way to do this is to define a constructor for the base class, and call this from the derived class initialization-list.
Hope that helps.
The right way to do it without breaking encapsulation would be for the base class to provide a constructor which we can call from derived class :
class Derived : public Base
{
public:
functions...
Derived(anotherElement) : Base(anotherElement)
{
}
}
class Base
{
public:
Base(anotherElement):privateElement(anotherElement) { }
private:
std::vector<float> privateElement;
}
Derived class cannot access private parts of the base class. That's because they are, well, private. Use protected if you want the derived class to have access to the base class' members without breaking the encapsulation.
Here is a sample of code that annoys me:
class Base {
protected:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base *b; /* Initialized by constructor, not shown here
Intended to store a pointer on an instance of any derived class of Base */
protected:
virtual void foo() { /* Some implementation */ };
virtual void foo2() {
this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
}
};
How do you access to the protected overrided function?
Thanks for your help. :o)
Protected members in a base-class are only accessible by the current object.
Thus, you are allowed to call this->foo(), but you are not allowed to call this->b->foo(). This is independent of whether Derived provides an implementation for foo or not.
The reason behind this restriction is that it would otherwise be very easy to circumvent protected access. You just create a class like Derived, and suddenly you also have access to parts of other classes (like OtherDerived) that were supposed to be inaccessible to outsiders.
Normally, you would do it using Base::foo(), which refers to the base class of the current instance.
However, if your code needs to do it the way you're trying to and it's not allowed, then you'll need to either make foo() public or make Derived a friend of Base.
One solution would be to declare a static protected function in Base that redirects the call to the private / protected function (foo in the example).
Lets say:
class Base {
protected:
static void call_foo(Base* base) { base->foo(); }
private:
virtual void foo() = 0;
};
class Derived : public Base {
private:
Base* b;
protected:
virtual void foo(){/* Some implementation */};
virtual void foo2()
{
// b->foo(); // doesn't work
call_foo(b); // works
}
};
This way, we don't break encapsulation because the designer of Base can make an explicit choice to allow all derived classes to call foo on each other, while avoiding to put foo into the public interface or explicitly turning all possible subclasses of Base into friends.
Also, this method works regardless of whether foo is virtual or not, or whether it is private or protected.
Here is a link to a running version of the code above and here another version of the same idea with a little more business logic.
It's a bit fragile, but with the classes you defined here, won't this work?
virtual void foo2() {
reinterpret_cast<Derived *>(this->b)->foo();
}
The reinterpret_cast points at the VTABLE for the base object, and calls it through this members accessor.
You call base functions explicitly with the scope operator (Base::foo()). But in this case, the Base class doesn't define foo (it's pure virtual), so there's actually no function to execute when you say this->b->foo(); since b is a pointer to Base and not Derived.
How do you access to the protected
overrided function?
--- from where?
You can access a protected member only via inheritance (apart from the methods of the same class). Say for example you have a class Derived1 which inherits from Derived, then objects of Derived1 can call foo().
EDIT: MSDN article on protected access specifier.