Suppose an object of class B is a member of class A.
class B{
//Definitions
}
class A{
public:
A();
B b_child;
int some_function();
}
One of the functions defined inside B needs to call a (public) function from its owner (parent?) A. Is there an immediate way to do this?
The only way I've managed to do this so far was to implement it outside the classes' definitions:
A a_obj;
a_obj.b_child.setowner(&aobj);
which tells b_child who is its owner. I don't like this. I'd rather use some builtin method for b_child to access its parent (if possible). If that's not possible, I'd rather pass the owner's address directly in the constructor for B, but I don't know how to reference A's address inside its definition.
There is no builtin method to get the 'owner' of a variable, whatever that means. Your approach of setting the owner is correct. Furthermore, doing so in the construction of B is also a correct decision. Sample code:
class B
{
public:
explicit B( A* owner ) : _owner( owner ) {}
...
private:
A* _owner;
};
class A
{
public:
A() : _child( this ) {}
...
private:
B _child;
};
Note some compilers may give you a warning for using this in that context, but its ok for the current example. Just make sure you don't call any A member functions from within B constructor, since the pointer you get still points to an unconstructed object at that stage.
I'd rather use some builtin method for b_child to access its parent (if possible).
No, it's not.
but I don't know how to reference A's address inside its definition.
You can use this pointer.
A() : b_child(this) { }
You should use this pointer to refer to the object within itself
class B{
//Definitions
}
class A{
private:
B b_child;
public:
A()
{
b_child.set_owner(this);
}
}
You should define B like the following:
template <class T, int N>
class B
{
public:
int example_func() { return static_cast<T&>(*this).some_function(); }
};
And then make B<A> a subclass of A (so it can call A directly).
class A : protected B<A,0>, protected B<A,1>
{
A();
int some_function() { return 42; }
};
This is called the curiously recurring template pattern.
If you don't want B to be a template class, and you're only going to use B with A, then the following is fine:
template <int N>
class B
{
public:
int example_func() { return static_cast<A&>(*this).some_function(); }
};
class A : protected B<0>, protected B<1>
{
A();
int some_function() { return 42; }
};
Alternatively, if you want to use B with not just A, but don't want to make B a template class (say, if you want a collection of pointers to B), you can do the following:
template <int N>
class B
{
public:
int example_func() { return some_function(); }
virtual int some_function() = 0;
};
class A : protected B<0>, protected B<1>
{
A();
int some_function() { return 42; }
};
This will resolve the some_function() call at run-time, and require a virtual pointer to be stored in your class.
Related
There is one file with two separate classes and one function:
int foo(int x) {return x+x;}
class A {
public:
int bar(){return foo(0);}
};
class B {
public:
int bar(){return foo(1);}
};
and they both need to use function
which uses only its argument (not use any data from A or B).
I can declare this function as global. But i would like to hide this function for other files (so this is un visible, unacccesible in other files). So i can declare this function as member function of each class A and B. But this will be code duplicate.
What is the best practice for that?
You can just omit any declarations of foo from any headers, and mark it static or define it in an anonymous namespace.
AB.h
class A { int bar(); };
class B { int baz(); };
AB.cpp
static int foo(int x) { return x+x; }
/* or
namespace {
int foo(int x) { return x+x; }
}
*/
int A::bar() { return foo(1); }
int B::baz() { return foo(2); }
You can simply place the function inside another class that only exists in that file:
class C
{
public:
static void foo(int) {}
};
class A
{
void test1()
{
C::foo(0);
}
};
class B
{
void test2()
{
C::foo(0);
}
};
A & B can access this function now and it's not being declared globally.
You can also put the function in its own namespace:
namespace ABFunctions
{
void foo(int) {}
}
And that is another way of keeping it separated, logically.
If you need to protect access, you can do it this way:
class C
{
friend class A;
friend class B;
private:
static void foo(int) {}
};
class A : C
{
void test1()
{
C::foo(0);
}
};
class B : C
{
void test2()
{
C::foo(0);
}
};
Now, only class A & B will have access to foo(int).
You can create a base class and derive from it. You won't have to duplicate code.
class Base {
virtual ~Base = 0;
protected:
int foo(int x) {return x+x;}
};
class A : public Base {...}
class B : public Base {...}
You can't instantiate an object of Base.
If it does not use any data from A or B, then it probably shouldn't be implemented within A or B. It sounds as if f was some kind of auxiliary function. Perhaps creating a class Utilities and making it a public static function of the utilities class would be better.
In c++ there's no hiding of functions at namespace level, though you can create a utility class that contains only private static functions, and explicitly specify which classes may have access using the friend keyword:
class C {
friend class A;
friend class B;
static void foo(int);
};
int foo(int x) {return x+x;}
class A {
public:
int bar(){return C::foo(0);}
};
class B {
public:
int bar(){return C::foo(1);}
};
Though that's not a very good design pattern, since friend introduces some more maintenance effort, as soon other classes than A or B need to access foo as well.
A probably better pattern is to use an interface as I've sketched out in my Q&A here:
How can I remove/refactor a «friend» dependency declaration properly?
The introduction of interfaces there suffers from the overhead of virtual polymorphism though. Maybe that could be resolved with introduction of static polymorphism via the CRTP.
Regarding a wider view for maintenance and reusing implementation details, why are you trying to hide these as rigorously claimed for the function foo(). Why do you need to hide this implementation detail at all?
Let's say I have the following class hierarchy:
class A {
int x;
};
class B : public A {
float y;
};
class Foo {
A* obj;
};
class Bar : public Foo {
B* obj; // I want this to override "obj" in the superclass!
};
I'm aware that Bar will shadow the obj of the superclass Foo, and that actually Bar will have two fields. But what I really want is that, if some code is able to see an object of type Bar*, they may also assume its pointer obj is referring to a type B. How can I accomplish this?
I've thought of two ways:
Add a template to Foo, which specifies the type of its pointer. Then, have Bar override as Bar : public Foo<B>. This adds templates and may be ugly.
Make the members protected, add getters in Bar which cast obj to B*, and make sure (in constructors, setters, etc.) that obj is only ever set to a B* type. This is inelegant because it's not really compile-time and requires a cast.
Are there better solutions available, that don't have the disadvantages of the above?
Thanks!
Try this thing:
class A {
int x;
};
class B : public A {
float y;
};
class Foo {
protected:
A* obj;
};
class Bar : public Foo {
B* obj; // I want this to override "obj" in the superclass!
public:
void edit_foo_obj(A* n_obj) {
Foo::obj = n_obj;
}
void edit_bar_obj(B* n_obj) {
this->obj = n_obj;
}
};
int main()
{
Bar b;
A a;
B ba;
b.edit_bar_obj(&ba);
b.edit_foo_obj(&a);
return 0;
}
The code below won't compile:
struct Base
{
std::vector<void(Base::*)(void)> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
Is it possible to refer derived class in template member x? In the example above I specify exactly Base and derived classes cannot push their own member functions into vector x.
Casting is bad since your code have to assume that this will be called only for instance of Derived class. This means that you either have to assume that all items in x are instance of Derived (in such case declaration of x is to general and should be changed to std::vector<void(Derived::*)(void)> x;) or you have to maintain extra information what which class method is stored in specific position of x. Both approaches are bad.
In modern C++ it is much better do do it like this:
struct Base
{
std::vector<std::function<void()>> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back([&d](){ d.foo(); });
Another good approach can be CRTP:
template<class T>
struct Base
{
std::vector<void(T::*)(void)> x;
};
struct Derived : public Base<Derived>
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
You may, but there is no implicit conversion; it requires a cast.
Derived d;
d.x.push_back(static_cast<void(Base::*)()>(&Derived::foo));
The caveat is the if you use that pointer to member with an object that isn't really a Derived, the behavior is undefined. Tread carefully.
As an addendum, if you want to get rid of the cast when taking the pointer, you can do that by encapsulating the push (with some static type checking to boot):
struct Base
{
std::vector<void(Base::*)(void)> x;
template<class D>
auto push_member(void (D::* p)()) ->
std::enable_if_t<std::is_base_of<Base, D>::value> {
x.push_back(static_cast<void(Base::*)()>(p));
}
};
I think I would express this by calling through a non-virtual member function on the base.
example:
#include <vector>
struct Base
{
std::vector<void(Base::*)(void)> x;
// public non-virtual interface
void perform_foo()
{
foo();
}
private:
// private virtual interface for the implementation
virtual void foo() = 0;
};
struct Derived : public Base
{
private:
// override private virtual interface
void foo() override {}
};
// ...
int main()
{
Derived d;
d.x.push_back(&Base::perform_foo);
auto call_them = [](Base& b)
{
for (auto&& item : b.x)
{
(b.*item)();
}
};
call_them(d);
}
Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.
I have a class A which has a private method called a(). I have also a class B which needs to access a() (but just B should have access to a(), thats why a() is private). I could now use a friend specifier but that would make other private methods of A (lets call them b() and c()) also available to B and I dont want that behaviour.
Is there a way to make just a() of A accessable to B?
There is a way -- if your class has a public template function:
class A {
// apparently private
void priv () { std::cout << "got you A::a()" << std::endl ; }
public:
template <class T>
void abuse() {}
};
struct Thief {};
template <>
void A::abuse<Thief>() {
this->priv();
}
int main() {
A a;
// obviously do not compile : a.priv();
// this i OK
a.abuse<Thief>();
return 0;
}
I must confess I stole this from GotW...
No there's not, but as you specify the precise class, just B could access A's private members.
You just have to take care of what method are called.
As friend relationship are not inherited, you don't have to worry about B's possible subclasses.
This could be done with some "twist".
Just factor out method a() from A class into a parent class that has B as a friend class, then let A inherit it. this will leave a() as being a method in A, but the only private method accessible by its parent's friend B.
here is a very simple code to clarify what I've said:
class parent
{
friend class B;
private:
void a() {}
};
class A:public parent
{
private:
void b() {}
void c() {}
};
class B
{
A* m_a;
public :
B()
{
m_a = new A();
m_a->a(); // OK
m_a->b(); // error C2248: 'A::b' : cannot access private member declared in class 'A'
}
};
hope it helps !
Yes, I have an easy way. Let B have a pointer of A::a(), like this:
typedef boost::function<void ()> functype;
class A {
private:
void a();
};
class B {
public:
void setfp(functype f) {m_f = f;}
void foo() {
// do some stuff
m_f();
}
private:
functype m_f;
};
A a;
B b;
b.setfp(boost::bind(&A::a, &a));
b.foo();