C++ virtual method: access rights, friends & Co - c++

I have some troubles understanding how to manage the access rights of virtual methods. I made two small code samples, but I can't understand how things work.
Code Sample 1
The first code contains 3 classes: a mother class Foo and two derived classes. The class Baz looks a little bit like a Composite. There's a virtual method, but it's protected.
class Foo
{
protected:
virtual void doIt() = 0;
};
class Bar : public Foo
{
protected:
void doIt()
{}
};
class Baz : public Foo
{
protected:
void doIt()
{
M_foo->doIt(); // Error here
}
private:
Foo* M_foo;
};
When trying to compile (Visual C++ 2010) this, I get an error: I can't call doIt from a pointer to Foo in the derived class. So, my understanding was "I can't call this method because it could actually call another one (e.g. the one of Bar) to which I have no right".
Code Sample 2
I decided to change a bit the design of the code and design a function instead of the virtual method. However, to access a protected method, I need to add friendship with my function.
class Foo
{
friend void doItPlease( Foo* foo);
protected:
virtual Foo* getChild() = 0;
};
class Bar : public Foo
{
protected:
Foo* getChild()
{ return 0;}
};
class Baz : public Foo
{
protected:
Foo* getChild()
{
return M_foo;
}
private:
Foo* M_foo;
};
void doItPlease( Foo* foo)
{
Foo* myFoo( foo->getChild() );
};
This code compiles fine. The problem is that I can't understand why: I have declared only the base class as friend, not the children classes and friendship is not inherited. But now, when I call getChild from the function, it is like I would call a method to which I have no right (the one in Baz e.g.).
Could someone explain me how are the rights related to virtual methods managed?

Those are the rules for protected. They allow access to the base class subobject, but not for any unrelated instances like yours.
If you google for protected, you will find advice to avoid it in the first place, use private and public only, the intermediate is quite rarely good.
The point is that you define privateness from base class' perspective. If some action is allowed from the outside, it's irrelevant that the unknown party is freestanding or happens to be a subclass. The only relevant attribute is it's being known to be trusted or not.
If the particular derived class is defined along with base, feel free to make it friend, just keep maintaining the rules.

class Foo
{
public:
friend class Baz;
protected:
virtual void doIt() = 0;
};
class Baz : public Foo
{
public:
Baz(Foo* foo)
: M_foo(foo)
{
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};

This could not work beacause Foo::doIt is an undifined virtual method method
class Baz : public Foo
{
protected:
void doIt()
{
Foo::doIt();
}
};
But if you have something like this it's should work fine
class Baz : public Foo
{
Baz()
{
M_foo = new Bar();
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};

Related

How do I use composition and inheritance together?

I've a case where an object and a collection of objects behave similarly. So to represent the object I've a class:
class A {
public:
virtual void foo();
protected:
int x;
};
And to represent the collection of objects, I've another class:
class Collection: public A {
void foo(); //override base class function
private:
vector<A*> aList;
}
This is fine, but the issue is that Collection class will have a copy of A::x which I don't need. I don't want class Collection to inherit the data members. How do I achieve this?
Note: I can't edit "class A" because it is from a library.
Correction: I can't change the interface of A. A is being used in rest of the code. I can modify the implementation. I can change A::anyFunction() to virtual if it is already not virtual. I can change a private member to protected.
You can use an interface:
class AInterface {
public:
virtual void foo() = 0;
};
and then
class A : public AInterface {
/*...*/
};
class Collection : public AInterface {
/*...*/
};
If you cant edit A you could still use the interface, by writing a wrapper:
class AWrapper : public AInterface {
void foo() { a.foo(); }
private:
A a;
};

C++ polymorphism use child constructor

I want to use child class constructor when parent object was given to a function.
class foo {
public:
virtual void doThing() { };
};
class bar : public foo {
public:
void doThing() override;
};
class bar2 : public foo {
public:
void doThing() override;
};
int main () {
bar obj;
bar2 obj2;
someFunction(&obj);
someFunction(&obj2);
}
void someFunction(foo *obj) {
//child object construction
}
If bar class object pointer was passed to a someFunction() then it would create new bar object inside function. Same thing with bar2 class and so on.
My question: is there a way to construct a child object when object's reference was given?
The typical way you do this is to provide a pure virtual "clone" method in foo, and then define it in the members.
The particularly good designers (A good designer is a lazy designer) use the Curiously Recursing Template Pattern (CRTP) to help this out.
class foo { public: virtual foo* clone() const=0; virtual ~foo(){}}
template <typename Derived>
class foo_helper : public foo
{
public:
virtual foo* clone() const
{
return new Derived(static_cast<const Derived&>(*this));
}
virtual ~foo_helper(){}
}
class Bar : foo_helper<Bar>
{
public:
virtual ~Bar(){}
}
see also:
http://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/

How to make a class able to access only certain private members of another class?

Suppose we have two classes:
class Base
{
private:
int x;
public:
void f();
};
class Foo
{
// some variables and methods
};
Now everyone can call Base::f(), but I want only Foo to be able to do so.
In order to achieve this effect, we can make Base::f() private and declare Foo as a friend:
class Base
{
private:
int x;
void f();
friend Foo;
};
The problem with this approach is that Foo has the access to both Base::f() and Base::x (and even to any other private members of Base). But I want Foo to have access only to Base::f().
Is there a way for a class (or a function) to grant an access only to certain private members of another class? Or maybe anyone could suggest a better approach to my problem?
EDIT:
I'll try to specify the access restriction I need. Firstly, Base is an interface in a library (it's an abstract class, in fact). The user uses only the classes derived from Base. Base::f() is called only by Foo which is another class in the library. Hiding Base::f() from the user is important, because only Foo knows when to call it. At the same time, Foo shouldn't mess up the other members of Base.
Very hacky, but this will allow very fine grained access.
class Base
{
private:
int x;
void f();
friend class Base_f_Accessor;
};
class Base_f_Accessor
{
private:
static void f(Base & b) { b.f(); }
friend class Foo;
}
class Foo
{
// some variables and methods
};
You can create another class that contains the data for Base like this:
class BaseData {
protected:
int x;
};
class Base : public BaseData {
friend class Foo;
void f ();
};
Now, Foo can access f as a method of Base like you wanted, but not x. Friendship is not commutative. By using protected, x appears private to everyone except those that derived directly from BaseData.
A better approach might be to use multiple inheritance to define Base, and provide Foo access only to those classes you want from which Base derives.
class With_f {
friend class Foo;
protected:
virtual void f () = 0;
};
class With_g {
protected:
virtual void g () = 0;
};
class Base : public With_f, public With_g {
int x;
void f () {}
void g () {}
};
Here, Foo would have to have a With_f pointer to Base, but it could then access the f method. Foo could not access g.
There's no easy, non-hackish way to achieve that. C++ simply doesn't have such access control granularity. You can play with some inheritance, but increased complexity outweighs any advantages this access restriction might have. Also, this approach doesn't scale - you can grant increased permissions only to one friend class.
Maybe a bit cumbersome, but you could make nested classes where the nesting class is friend, then you can add friends per nested class. This gives some level of granularity:
#include <iostream>
class Nesting
{
friend class Foo;
class Nested1
{
friend class Nesting;
public:
Nested1() : i(3) { }
private:
int i;
} n1;
class Nested2
{
friend class Nesting;
friend class Foo;
public:
Nested2() : j(5) { }
private:
int j;
} n2;
int f() { return n1.i; }
};
class Foo
{
public:
Foo(Nesting& n1) : n(n1) { }
int getJ() { return n.n2.j + n.f(); }
private:
Nesting& n;
};
int main()
{
Nesting n;
Foo foo(n);
std::cout << foo.getJ() << "\n";
}

Calling a chain of functions at different class inheritance levels

Given:
class Foo {
public:
void Method1();
}
class Bar extends Foo {
public:
Bar* Method2();
}
class Baz extends Bar {
public:
Baz* Method3();
}
So,
someObject *b = new Baz();
b->Method3()->Method2()->Method1();
This will work, as Baz() contains all methods including Method2(), Bar contains Method1();
But, due to return type this seems to be a bad idea - when accessing simpler Method1() at first inheritance level before calling more complex Method3(), and having to keep this calls in single line..
b->Method1()->Method2()->Method(3); // will not work?
Also, someone told me that putting try.. catch.. throw inside one of those Method's will occasionally exit the chain without calling next method at wrong value. Is this true?
So how to properly implement method chaining in C++?
That's what virtual methods are for. From the syntax errors I gather that you are new to C++
struct Base
{
virtual Base* One() { return this; };
void TemplateMethod() { this->One(); }
};
struct Derived : public Base
{
virtual Base* One() { /* do something */ return Base::One(); }
};
When you call TemplateMethod:
int main()
{
Base* d = new Derived();
d->TemplateMethod(); // *will* call Derived::One() because it's virtual
delete d;
return 0;
}

Figuring out the class of an inheriting object

I have a linked list of Foo objects. Foo is a base class, which has several classes inherit from it. Say, classes A, B, and C.
I am cycling through this linked list and calling a method some_method, which has 3 definitions; one for each child class:
some_method(A a);
some_method(B b);
some_method(C c);
The linked list is generic, so it is of type Foo, as it has an assortment of A, B and C objects.
When I'm cycling through the linked list at current_element, calling some_method(current_element);, how can I make it call the right method? The compiler complained until I wrote a some_method that took the generic Foo, and it only calls into that method.
Depending on your requirements, you may want to consider using polymorphism. To do this, add a pure virtual method to your base node class, and move the corresponding methods to the derived classes.
class Foo
{
public:
virtual void some_method() = 0;
};
class A : Foo
{
public
virtual void some_method()
{
// move the body of some_method(A a) here
}
};
For this to work, your linked list will need Foo*, instead of Foo.
class Node
{
public:
Foo* foo;
Node* next;
};
// ...
Node* someNode = GetNode();
// Calls correct method - A::some_method, B::some_method, or C::some_method
someNode->foo->some_method();
If you can't put some_method in Foo/A/B/C, then you might want to look into the Visitor design pattern:
http://en.wikipedia.org/wiki/Visitor_pattern
This is the "double dispatch" problem. You can use the visitor pattern. Usually the Visitor is a base class so you can re-use this design for multiple problems.
#include <iostream>
class FooVisitor;
class Foo
{
public:
virtual void some_method() = 0;
virtual void visit(FooVisitor* v) = 0;
};
class A;
class B;
class FooVisitor
{
public:
virtual void visit(A* a){ std::cout << "A" << std::endl;}
virtual void visit(B* b){std::cout << "B" << std::endl;}
};
class A : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
class B : public Foo
{
public:
virtual void some_method()
{
// move the body of some_method(A a) here
}
virtual void visit(FooVisitor* v) { v->visit(this);}
};
int main()
{
FooVisitor fv;
Foo* f1 = new A;
f1->visit(&fv);
Foo* f2 = new B;
f2->visit(&fv);
getchar();
}
Two ways:
1) the better way:
Reverse your design such that someMethod is a virtual method of the base class Foo and redefine it in the derived classes. As:
class Foo {
public:
virtual void someMethod() = 0;
};
class A {
public:
void someMethod() { /* implementation specific to A here */ };
};
class B {
public:
void someMethod() { /* implementation specific to B here */ };
};
class C {
public:
void someMethod() { /* implementation specific to C here */ };
};
Then calling the someMethod on a pointer to Foo will automatically call the method from the appropriate class. If that cannot be done because someMethod cannot be implemented as part of Foo or its derivatives (e.g. it needs access to private members of the class it is currently in in your design), then you might try to split this functionality apart into subproblems that can be put into virtual methods of these classes A B C.
2) the "I don't have a choice" way:
Use RTTI (Run-Time Type Identification), it is included in C++. It requires that your base class Foo has at least one virtual method. You need to #include <typeinfo>, then use typeid() on the pointer, it will return a type_info object, and you can compare its name() result with the class names A B and C. This isn't a very nice approach because it has more overhead and it breaks OOP design principles. But if that's the only option, it's fine.
RTTI is your friend here. The example given in the link will guide you further
You can call the method for the child class as a member method. For exampleA a = new A(); a.some_method() should call the correct the method. Within some_method() you can reference to object using keyword this.