I realy don't understand why it works, but below code shows an example of calling private method from the world without any friend classes:
class A
{
public:
virtual void someMethod(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void someMethod(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->someMethod();
}
outputs:
B::someMethod
Doesn't it violates encapsulation rules in C++? For me this is insane. The inheritance is public, but the access modifier in derived class is changed to private, thus the someMethod() in class B is private. So in fact, doing a->someMethod(), we are directly calling a private method from the world.
Consider the following code, a modification of the code in the original question:
class A
{
public:
virtual void X(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void Y(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->X();
}
It's easy to understand that it's legit to call X(). B inherits it from A as a public member. Theoretically if X() would call Y() this would be legit as well of course, although this is not possible because X() is declared in A which doesn't know Y(). But actually this is the case if X = Y, i.e. if both methods have the same name.
You may think of it as "B inherits a public method from A, that calls a private method (of B) with the same name".
a is a pointer to an A object where the method is public, so this is not a violation. Since, you have used virtual, the VTABLE is taken into account and you get the output as B::someMethod.
For me this is quite simple.
As you are allowed to asign any dynamic type inheritance of a class to an object of the parrent-class it would be vise versa.But as you are assigning the Child to its parrent object pointer this could be bad as if the class of B where bigger as A.
If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:
the dynamic type of the object,
a cv-qualified version of the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,
a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
a char or unsigned char type.
So as in your code you aren't fitting this conditions, but as B has the sime size as A, it would be possible to run it. But it is undefined behavior.
And as you creat a new B the memory block a is pointing to has the method of printing B and not A.
The access control specifiers (public, protected and private) do not apply to member functions or data members. They apply to member function and data member names. And that works. If you can refer to the member without the name, you can access it.
That's precisely what's happening here. You're calling B::someMethod, but you're calling it using the name A::someMethod, which is public. No problem.
You're suggesting a private member function shouldn't be callable from outside of the class (disregarding friends for the moment). How would your desired semantics work in the following case?
Shared library hider:
hider.h:
typedef void (*FuncType)();
class Hider {
private:
static void privFunc();
public:
static void pubFunc();
FuncType getFunction() const;
};
hider.cpp
#include <cstdlib>
#include <iostream>
#include "hider.h"
void Hider::privFunc() {
std::cout << "Private\n";
}
void Hider::pubFunc() {
std::cout << "Public\n";
}
FuncType Hider::getFunction() const {
if (std::rand() % 2) {
return &pubFunc;
} else {
return &privFunc;
}
}
Application using library hider
#include "hider.hpp"
int main()
{
Hider h;
FuncType f = h.getFunc();
f();
}
What about the call to f()? Should it fail at runtime 50% of the time with some form of access control violation?
As suggested by DyP in the comments, a more realistic scenario is the well-known "template method" design pattern:
class Container
{
public:
void insert(const Item &item) {
preInsert();
data.insert(item);
postInsert();
}
private:
std::vector<Item> data;
virtual void preInsert() = 0;
virtual void postInsert() = 0;
};
class ThreadSafeContainer : public Container
{
private:
std::mutex m;
virtual void preInsert() {
m.lock();
}
virtual void postInsert() {
m.unlock();
}
};
Your semantics would mean this code wouldn't compile.
Related
Is it possible to acces a member of a derived class using a pointer to the base class?
// Example program
#include <iostream>
#include <vector>
#include <memory>
#include <string>
class A {
public:
std::string x = "this is the wrong x\n";
};
template <class T>
class B : public A {
public:
T x;
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
std::cout << element->x;
}
}
Here I'm always getting the output from class A. I cannot typecast it because I don't know whether the element is of type A or type B in advance. Is there a proper way to do this?
The proper way would be to make a virtual function to perform the task like printing.
class A {
public:
std::string x = "this is the wrong x\n";
virtual ~A() = default;
virtual void print() const { std::cout << x; }
};
template <class T>
class B : public A {
public:
T x;
virtual void print() const override { std::cout << x; }
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
element->print();
}
}
If you have a pointer to a base class, you can only access things defined on that base class (without typecasting). For all the compiler knows, it is an instance of the base class and has nothing else.
Polymorphic behavior involves using virtual functions - derived classes can change which function is called when invoking a virtual function of the base class. Note that this mechanism does not exist for members (what would you change about a member? There's only the type, and changing that in a derived class makes no sense). So the only meaningful thing you can do with pointers to base classes that should have customized behavior is to call their virtual functions.
Now, you could think "ok, I'll just make access to x go through a virtual function", but the problem here is that you must specify the involved types when you declare the virtual function in the base class already. That makes sense: The compiler needs to know which types a function involves, even a virtual one. You may only pass and return different types in the overriding functions if they are "compatible" - see covariance and contravariance for more information.
So unless all your T are covariant, virtual functions cannot help you either.
The core flaw with your concept is that you want to have some type (i.e. element->x) in a non-templated function depend on the dynamic type of some object (i.e. element). That is impossible because the compiler must know the type of each expression at compile-time. So you must approach your problem differently.
I have the following class
class A {
private:
B b;
public:
A();
}
class B {
public:
void foo();
void bar();
void foz();
........
}
B has a lot of methods. Sometimes is needed for a "customer" of class A to use method of class B. I could return a reference of B, but in this case I should return a const reference because returning a non-const reference of a private object is not good programming. If the reference is const, foo, bar and so on can't be called because they aren't const. So the only "clean" way seems to recreate the same interfaces in A using delegation to B. But this approach is not really good because I should recreate all the interfaces in A. As alternative I could set B as public in A, but it seems "strange" to me. What should I do in this case?
That is mainly an encapsulation question, and what you want to advertise in the public interface of class A.
If class B is also a public class - read can normally be used by users of class A and not a class internal to a library or framework - and if you want the existence of a B subobject to exist in the public documentation of class A and if you want to allow any operation on the B object, you can safely provide a getter.
If any of the above conditions is false, then the getter would break encapsulation and you would better define delegating methods in class A.
Depending on the general design, it could make sense to declare an interface class (say C) with only the methods that you want to allow from class A, and have B a subclass from C. Then you could safely declare a getter returning a reference on a C object:
class C {
public:
void foo(); // optionally virtual or pure virtual...
void bar();
void foz();
};
class B: public C {
.... // other members not relevant for what is public for A users
};
class A {
private:
B b;
public:
A();
C& getB() {
return b;
}
};
Solution 1. You create a getb() and return reference to B. Its not bad programming in you case particularly.
Solution 2. Create interface function for each corresponding function of b and call them.
void A::foo()
{
b.foo();
}
You can make the data member protectedinstead of private. Documentation says that protected members are not as private as private members, which are accessible only to members of the class in which they are declared, but they are not as public as public members, which are accessible in any function. protectedmembers (be they data members of method members) serve the role you're looking for : they are not accessible from everywhere (safe coding practices), but you can still manage them in clean ways when it makes sense :
If class A has an attribute of type B, is has access to B's
protected and publicmembers
friendfunctions can access both protected and publicmembers of a class they are friend with.
When preceding the name of a base class, the protected keyword specifies that the public and protected members of the base class are protected members of its derived classes.
Here, you're interested by the first item of the list : you can access B' methods from A; BUT B has still safeguards.
When I run the following code (adapted from your code) :
#include <iostream>
using std::cout;
using std::endl;
class B {
public:
void foo() { cout << "foo" << endl; };
void bar() { cout << "bar" << endl; };
void foz() { cout << "foz" << endl; };
};
class A {
protected: // <===== THIS IS THE SIGNIFICANT BIT
B b;
public:
A() {
b.foo();
b.bar();
b.foz();
cout << "A constructor" << endl;
};
};
int main(int argc, char** argv) {
A myA;
return 0;
}
I get the following console output :
foo
bar
foz
A constructor
Which shows that I can access B's methods from A.
Suppose I have defined two classes based on one basic class:
class Basic
{
public:
int i;
};
class DerivedA:public Basic
{
public:
int j;
};
class DerivedB:public Basic
{
public:
int k;
};
Then now have a class named Collect, which contains the pointer to the Basic class
class Collect
{
public:
Basic *pBasic;
void run();
};
In this class, a function run() has been defined, which will perform some operations based on the type of the object the pointer points to:
void Collect::run()
{
if (pBasic points to DerivedA object)
{
}
if (pBasic points to DerivedB object)
{
}
};
Then my question is as follows:
With C++, is it possible to know the type of object the pointer points to?
Is it a good practice to perform something different based on the type of object the pointer points to as illustrated in run function?
To perform a check like this your base class Basic needs to have at least one virtual member. Since you wish to build a class hierarchy, I would tend to make ~Basic virtual to ensure it will be properly deleted at the same time.
The reasoning behind this is that the by including a virtual member, you force each object of the class to contain a pointer to the class specific vtable, which the implementation can then use to perform your check.
class Basic
{
public:
int i;
virtual ~Basic() { }
};
class DerivedA:public Basic
{
public:
int j;
};
class DerivedB:public Basic
{
public:
int k;
};
Now you can write your check:
void Collect::run()
{
if (DerivedA* pDerived = dynamic_cast<DerivedA*>(pBasic)) { }
if (DerivedB* pDerived = dynamic_cast<DerivedB*>(pBasic)) { }
};
The dynamic_cast will return a nullptr if it fails, so you will only enter the body of the if when your cast succeeded and pDerived contains a valid pointer to the right derived object.
In c++ we usually use Base class, not Basic class.
Anyway, in general, if your base class is polymorphic (that contains virtual functions) you can use dynamic_cast:
class Base {
public:
Base();
virtual ~Base();
void test() { cout << "Base" ; }
};
class Derived: public Base {
public:
void test() { cout << "Derived" ; }
};
void main() {
Base* a = new Derived();
if(dynamic_cast<Derived*>(a)) {
a->test(); /* print "Derived" */
}
}
This means that object "a" has "static-type": Base; and "dynamic-type": Derived.
Unless your base class have virtual functions, the pointee of your pointer will always be of type Basic, and have the behavior of an object of type Basic. Actually, even with virtual function, a pointer of type Basic* always points to an object of type Basic. But the ''dynamic type'' of the pointee can be different.
If your base class have at least one virtual function, then your can rely on the Run-time type information: you can use dynamic_cast or typeid to get the dynamic type of the pointee.
It seems that a protected member from a template policy class is inaccessible, even with a class hierarchy which seems correct.
For instance, with the following code snippet :
#include <iostream>
using namespace std;
template <class T>
class A {
protected:
T value;
T getValue() { return value; }
public:
A(T value) { this->value = value; }
};
template <class T, template <class U> class A>
class B : protected A<T> {
public:
B() : A<T>(0) { /* Fake value */ }
void print(A<T>& input) {
cout << input.getValue() << endl;
}
};
int main(int argc, char *argv[]) {
B<int, A> b;
A<int> a(42);
b.print(a);
}
The compiler (clang on OS X, but gcc returns the same type of error) returns the following error :
Untitled.cpp:18:21: error: 'getValue' is a protected member of 'A<int>'
cout << input.getValue() << endl;
^
Untitled.cpp:25:5: note: in instantiation of member function 'B<int, A>::print' requested here
b.print(a);
^
Untitled.cpp:8:7: note: can only access this member on an object of type 'B<int, A>'
T getValue() { return value; }
^
1 error generated.
The strange thing is that the last note from the compiler is totally correct but already applied since the b object is of type 'B<int, A>'. Is that a compiler bug or is there a problem in the code ?
Thanks
You have misunderstood the meaning of protected access.
Protected members are callable by derived classes. But only on the base object contained inside the class itself.
For example, if i simplify the problem, using :
class A {
protected:
void getValue(){}
};
class B : protected A
{
public:
void print(A& input)
{
input.getValue(); //Invallid
}
};
getValue cannot be called on a "A" object other than the "A" object inside the class itself.
This for example is valid.
void print()
{
getValue(); //Valid, calling the base class getValue()
}
As pointed out by Dan Nissenbaum and shakurov. This is however also valid:
void print(B& input)
{
input.getValue();
}
This is because we explicitly say that input is a object of B. And the compiler know that all that objects of B has protected access to getValue. In the case when we pass a A&, the object might as-well be a type of C, wich could be derrived from A with private access.
Let's forget for a minute about the template and look at this:
class A {
protected:
int value;
int getValue() { return value; }
public:
A(int value) { this->value = value; }
};
class B : protected A {
public:
B() : A(0) { /* Fake value */ }
void print(A& input) {
cout << input.getValue() << endl;
}
};
The print() method's implementation is wrong because you can't access non-public member of A inside B. And here's why: from within B, you can only access non-public members of B. Those members may be either inherited or not — it doesn't matter.
On the other hand, A& input may not be a reference to an instance of B. It may be a reference to another subclass (which may well have getValue() inaccessible).
Member functions of a derived class have access to protected base class members within any object of its type that is passed as an argument so long as the explicitly declared class of the object passed as an argument is that of the the derived class (or a further derived class).
Objects explicitly passed as the base class type cannot have their protected members accessed within the derived class's member functions.
In other words, if we have:
class A
{
protected:
int x;
}
class B : public A
{
void foo(B b)
{
b.x; // allowed because 'b' is explicitly declared as an object of class B
}
void goo(A a)
{
a.x; // error because 'a' is explicitly declared as having *base* class type
}
};
...then the line a.x is not allowed because the explicit type of the argument is A, but the rule for protected access only applies to objects explicitly defined as the same class as the class attempting to access the member. (...Or a class derived from it; i.e., if class Cderives from B, then passing an object explicitly declared as an object of class C will also have x accessible within B member functions.)
The reason for this is given by shakurov when he writes (paraphrasing)
A& input might not be a reference to an instance of B. It may be a
reference to another subclass (which may well have getValue()
inaccessible)
An excellent explication of this answer is also given here: accessing a protected member of a base class in another subclass.
As a matter of interest, I believe that this comes from the C++ standard here:
11.4 Protected member access [class.protected] 1 An additional access check beyond those described earlier in Clause 11 is applied when a
non-static data member or non-static member function is a protected
member of its naming class (11.2)115 As described earlier, access to a
protected member is granted because the reference occurs in a friend
or member of some class C. If the access is to form a pointer to
member (5.3.1), the nested-name-specifier shall denote C or a class
derived from C. All other accesses involve a (possibly implicit)
object expression (5.2.5). In this case, the class of the object
expression shall be C or a class derived from C.
Don't get distracted by the template. It has nothing to do with the error. The line in main that the compiler is complaining about creates an object of type B<int, a> and tries to access a protected member. That's not legal, regardless of the type. You can only use protected members from inside a member function or friend function. For example:
struct S {
protected:
void f();
};
int main() {
S s;
s.f(); // error: attempts to call a protected member function
}
i have two classes (non-static) A & (static) B.
I am trying to store Object A into B so that i can use its functions in funcB().
However i do know that static classes cannot store non-static variables & functions. is there anyway to get pass this rather than converting Class A into a static class?
class A
{
public:
A();
void funcA();
private:
int A;
};
class B
{
public:
B(A *objA);
static void funcB();
private:
A *objA;
};
edit:
I stated static class to make it easier to explain. i did not know the correct term.
So the question is actually: How do i use a non-static member from a static function?
You can not access anything that is specific to an instance of a class from a static function by itself. A static function has no "this" pointer (the compiler passes a pointer to the instance of the object calling the function for non-static functions). You can get around this by passing a pointer to the object you want to modify, but then why are you using a static function? My advice would be to avoid what it seems like you are trying to do, but I provided 2 ways to do it below (as a good learning example).
See below for an example of using
#include <iostream>
using namespace std;
class A
{
public:
A(int value) : a(value){}
void funcA();
public:
int a;
};
class B
{
public:
B()
{
objA = new A(12);
}
void funcB2()
{
B::funcB(*objA);
}
static void funcB(A const & value)
{
cout << "Hello World! " << value.a << endl;
}
private:
A *objA;
};
int main()
{
A a(10);
B::funcB(a);
B b;
b.funcB2();
return 0;
}
I think you just should not make design like this. A static function is initialized when the non-static members are not ready. You said "the class A, links to many other classes and has stored many other information. Class B on the other hand, has to be static due to some windows API threading condition." . In this case, can you change your design and turn A into static class?