I have situation similar to included:
class A
{
public:
A(shared_ptr<B>);
}
class B : public enable_shared_from_this<B>
{
const shared_ptr<A> a;
}
I can't have shared_ptr to B before construction, so before a is initialized. So, I need to initialize my constant field after construction (I think it denies RAII), or just construct it later (so it can't be const, so it denies const-correctness, and also looks like not-too-consistent with RAII).
It looks like propably common situation. Is there any the cleanest way to handle this? How would you do this?
I would solve this by not having const members, plain and simple. They are generally much more trouble than they're worth (they make the class non-assignable, not even move-assignable, for example).
a is private, so only the class itself can access it. Thus it should be enough to document "a should never be modified after being initialised!!!". If you fear that won't be enough (or the class has friends outside your control), you can make this even more obvious like this:
class B : public enable_shared_from_this<B>
{
const std::shared_ptr<A>& a() { return _use_this_ONLY_for_initialising_a; }
std::shared_ptr<A> _use_this_ONLY_for_initialising_a;
};
Such a situation is a good indicator to refactor your code. Think about whether B should actually inhert from A or be a member of A before finding a way around this problem...
.. because it is probably going to be to remove the constness of your object - and probably not use shared_ptr (you have a cyclical reference there, so ref-counting alone will never be able to destroy your objects!).
If A doesn't actually keep a copy of the shared_ptr<B> you pass it (just uses the B briefly) then you can make this work (see below) but:
If A doesn't keep a reference to the B then it could just take a B& or B* argument, not a shared_ptr<B>, so you should change the design.
If A does keep a reference then you're going to have a circular reference, so you should change the design.
This works, but is really, really horrible and would be easy to introduce bugs, and is generally a bad idea, I probably shouldn't even be showing it, just change your design to avoid circular dependencies:
#include <memory>
#include <iostream>
class B;
class A
{
public:
A(std::shared_ptr<B> b);
};
class B : public std::enable_shared_from_this<B>
{
// return a shared_ptr<B> that owns `this` but with a
// null deleter. This does not share ownership with
// the result of shared_from_this(), but is usable
// in the B::B constructor.
std::shared_ptr<B> non_owning_shared_from_this()
{
struct null_deleter {
void operator()(void*) const { }
};
return std::shared_ptr<B>(this, null_deleter());
}
public:
B(int id)
: m_id(id), a(std::make_shared<A>(non_owning_shared_from_this()))
{ }
int id() const { return m_id; }
private:
int m_id;
const std::shared_ptr<A> a;
};
A::A(std::shared_ptr<B> b)
{
std::cout << b->id() << std::endl;
}
int main()
{
auto b = std::make_shared<B>(42);
}
Related
I have a code where by design some classes use a factory function to generate the actual class, and others do not. Many classes have functions with the same names implemented and those functions are called sequentially (see below). This design results in mixing smart pointers to objects and objects itself. Is the code below bad design and should I use smart pointers everywhere?
#include <iostream>
#include <memory>
class A
{
public:
void print_name() { std::cout << "A\n"; }
};
class B
{
public:
virtual void print_name() = 0;
static std::unique_ptr<B> factory(const int n);
};
class B1 : public B
{
public:
void print_name() { std::cout << "B1\n"; }
};
class B2 : public B
{
public:
void print_name() { std::cout << "B2\n"; }
};
std::unique_ptr<B> B::factory(const int n)
{
if (n == 1)
return std::make_unique<B1>();
else if (n == 2)
return std::make_unique<B2>();
else
throw std::runtime_error("Illegal option");
}
int main()
{
A a;
std::unique_ptr<B> b1 = B::factory(1);
std::unique_ptr<B> b2 = B::factory(2);
// The block below disturbs me because of mixed . and ->
a.print_name();
b1->print_name();
b2->print_name();
return 0;
}
EDIT
I have added smart pointers to the example following the comments below.
This looks like a reasonable design to me. In the client code you will work through the base class interface.
class Base {};
class A: public Base {};
class B: public Base {};
class B1: public B {};
class B2: public B {};
class Factory {
std::unique_ptr<Base> create(const int n) {
// Instantiate a concrete class based on n
return std::unique_ptr<Base>(new A());
}
}
Generally, you should avoid using pointers, if not needed. Topics like Return Value Optimization make them optional in most cases. Also, don't use C-Style-Pointers. C++11 introduced the memory-header, which includes many useful smart pointers.
And yeah, I feel like using those pointers in such a program is a bad design decision.
Other than the mix, why does the code disturb you? What do you think could actually go badly because of it? Do you think the difference really hurts readability?
Yes the lines that call print look different, and that difference tells you that the objects are being managed in a different way.
There's no obvious benefit to them being made the same, if a developer can't understand both . and -> then you have much bigger problems.
I've worked on a codebase where nearly everything was handled by shared pointers for consistency, even though some things shouldn't be pointers and most aren't really shared. Needless inconsistency should be avoided but it really isn't helpful to be consistent in cases where that hides legitimate difference.
One benefit of your code over all pointers is that since a is not a pointer you can sure that a is not null.
Hi I am pretty new to C++ and im converting C code to C++. I started by converting all the structs to classes, and added accessors and mutators for the internals, but some structs have other structs inside them. I want to know the best method for setting the internals of a class within a class, such as
struct1.struct2.struct3.i = 5;
where i is an int. Should I be passing as reference using accessors? but seeing as accessors tend to be const would this be something I should do?
something like
class1.get_class2().get_class3().set_i(5) or something if it can be done in this kind of format.
This is probably a dumb question but i have no idea how to do it, Thank You
class1.get_class2().get_class3().set_i(5)
is possible if get_class2() is non-const and returns a non-const pointer reference.
However, this approach completely breaks the encapsulation. The users of class1 should not (and must not) know that class1 uses class2 inside and that in turn uses class3 inside.
If a setter-API is absolutely necessary, then a better approach is do it hierarchically. For example
// User
class1.set_i( 5 );
// class1
class1::set_i( int x ) { class2_obj.set_i( x ); }
// class2
class2::set_i( int x ) { class3_obj.set_i( x ); }
// class3
class3::set_i( int x ) { i_ = x; }
I am not so sure about that ... did you put a class inside a class or an object inside a class ?
something like :
class OBJ1
{
//methods , and other stuff
}
class OBJ2
{
public OBJ1 *O ;
}
is valid , so you can acces a method like :
OBJ2 *N2 ;
N2->O->some_method();
however , something like
class OBJ2
{
class OBJ1;
}
is not valid :P
again... not sure if this is exactly what you asked ...
If you really have a good reason to access your member object via getters and setters, you can do the following:
class A {
public:
void f() const {}
};
class B {
public:
const A &get_a() const {
// the returned reference will be read-only, i.e. only non-const member
// functions can be called, and public members can not be written.
// it needs to be stored in a const A & object.
return a;
}
A &get_writable_a() {
return a;
}
void set_a(A &a) {
//make sure that the assignment operator of A will take care of all the
//dirty internals, such as internal buffers that need to be deleted.
this->a = a;
}
private:
//the member
A a;
};
int main() {
B b;
b.get_a().f();
}
If you don't have a good reason to do so, I'd recommend to simply make it a public member, and access it directy:
class A {
public:
void f() const {}
};
class B {
public:
A a;
};
int main() {
B b;
b.a.f();
}
Isn't that simply much more elegant?
Note that you can use friend to specify other functions or classes that are allowed to directly access your private members.
As was also pointed out in an other answer, in most cases it is a bad idea to make a member object visible to the outside at all.
I'm a newbie using V++ and I've been wondering about some memory behavior.
I wrote similar classes to what is causing me problems. The questions are
written in the comments of the code.
class A
{
private:
int _number;
public:
A(int number) : _number(number)
{}
const int& getNumber() const
{
return _number;
}
void setNumber(const int& number)
{
_number = number;
}
}
class B
{
private:
A _a;
bool _hasA;
public:
B() : _hasA(false)
{}
B(const A & a) : _a(a), _hasA(true)
{}
void setA(const A & a)
{
_a = a;
}
const A& getA() const
{
return _a;
}
const bool hasA() const
{
return _hasA;
}
void removeA()
{
// ??
}
}
int main()
{
A a(5);
B b1; // Is the A space allocated even if no value is affected to it ?
B b2(a);
b1.setA(b2.getA()); // I actually want to move "a" from b2 to b1 without leaving it in b2
b1.removeA(); // Do I need to write a removeA() function and how would it be?
}
b1.setA(b2.getA()); copies A into b1 too instead of moving it.
Thanks for your help.
EDIT: To answer those who are confused like I just was:
Me : I just understood that when instanciating b1 it needed the A::A() constructor. I thought it'd be like "null" or something if I created b1 without instantiating _a.
Zac Howland: #SanjamX I see your confusion now. In managed languages, (most) everything is a pointer, so if you do not instantiate it (e.g. A a instead of A a = new A()), it is just a null pointer. In C/C++, if you declare something as A a, you instantiated it "on the stack". It is an automatic variable that will be deallocated when it goes out of scope. You are still instantiating it, however. This question may help you understand better.
B b1();
That does not do what you think it does. It is declaring a function b1 that takes no parameters and returns a B.
b1.setA(b2.getA());
b1.removeA();
Because of the previous situation, the 2 lines above will give you a compiler error.
The "move" you are asking about will actually be a copy (in this case). You can use the C++11 move semantics to do an actual move, but it is entirely unnecessary with the current code. Alternatively, you can change your class to do a move using pointers (which could potentially be useful) - which would use std::unique_ptr<A> _a, instead of A _a.
Suppose I have my classes as:
namespace scope
{
class A
{
private:
int a;
public:
...
};
class B
{
public:
...
A method();
...
};
};
The method definition:
A B::method()
{
A object;
object.a = 3; // private member access error
// access via object (pointer) error if inheritance is used
return object;
}
The most common way to solve the access error is to use setters+getters.
However I don't want any other scope (or someone using the API) to set A.a, so a public setter method is forbidden for this case.
a may be public but it should be read-only on API side. It should be read+write on the source side, because, for instance, I want to set it with B::method. How can I achieve this behaviour?
I tried inheritance, also friend relation. I also played with immutable and const property declarations. The problem with these is, when I declare A object with the default constructor, property is set to some value like -918316838410 (which might arise from the fact that I'm not using extern, I'm not sure) and cannot be set by method later on.
Any ideas will be appreciated. Thanks in advance.
You want B to have access to A that you don't want other people to have?
That is friendship.
Add friend class B, into the class A definition, and all will be happiness.
btw the common examples for this are when I am using multiple classes to generate a single interface. Eg: things like list<> and map<> usually need node classes, and those classes often want friend access on each other. This breach of encapsulation is fine, since they are really one big class from a logical perspective.
Be warned, most people should use friends rarely or never, its mostly for library writers, not for general programming.
Just like Richard said, you can use friendship. But keep in mind that when you need friendship, you should probably think again about your design. As Richard saids too, maybe putting a as a parameter of A constructor should do exactly what you want.
Here is a working example with friendship :
#include <iostream>
namespace scope
{
class A{
friend class B;
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
};
class B{
public:
A method(){
A a;
a.a=3;
return a;
}
};
int main(){
scope::B b;
scope::A a = b.method();
a.print(); //just to see it works...
}
Here is a way to do the same without friendship and keeping a private (Ok its ugly :-)
#include <iostream>
namespace scope
{
class B;
class A
{
private:
int a;
public:
void print(){
std::cout << a << std::endl;
}
// A way to only allow B instances to give a correct value
// of "a" member
void pleaseClassBSetMyPrivateMember(B& b);
};
class B
{
public:
A method(){
A a;
a.pleaseClassBSetMyPrivateMember(*this);
return a;
}
int computeValueForMemberOfClassA(A& a){
// you can access public members of a to
// calculate the proper value of a.a member
return 3;
}
};
void A::pleaseClassBSetMyPrivateMember(B& b)
{
// ask for class B object the correct value for member a
a = b.computeValueForMemberOfClassA(*this);
}
};
Per my previous question, I wish that a boost::shared_ptr<A> was actually a subclass of A (or perhaps A*) so that it could be used in methods that took A* as their argument.
Consider the following class:
class A
{
public:
A(int x) {mX = x;}
virtual void setX(int x) {mX = x;}
virtual int getX() const {return mX;}
private:
int mX;
};
In the previous question, I proposed the creation of a SharedA object to take care of this, and presumably it does.
class SharedA : public A
{
public:
SharedA(A* a) : mImpl(a){}
virtual void setX(int x) {mImpl->setX(x);}
virtual int getX() const {return mImpl->getX();}
private:
boost::shared_ptr<A> mImpl;
};
It would be Grrrrrrrreat thought, if I could create a template class to take care of all of this for me.
template <class T>
class Shared : public T
{
public:
SharedT(T* t) : mImpl(t)
{
//What kind of crazy voodoo goes here?
}
private:
boost::shared_ptr<T> mImpl;
};
If I had this, (along with the proper constructors in Shared<T>), then I could do the following:
A* indestructo_A = new Shared<A>(new A(100));
A* indestructo_A_clone = new Shared<A>(indestructo_A);
delete indestructo_A
cout << "Indestructo-A back with a vengence!" << indestructo_A_clone.getX();
Questions:
Is this useful? Or is its utility only in corner cases where you're dealing with particularly bad code. For instance:
void aFunctionYouHaveToUse(A* a)
{
/some useful algorithm and then/
delete a;
}
Is it possible to build such a templated class? (I guess you need reflection, right?) If you can build it, how?
There's a really, darn good reason why shared_ptr does not allow explicit casting to A* (there are better ways of doing it than inheriting, which would be impossible anyway). The whole purpose of shared_ptr, and other smart pointers, are to provide a small, encapsulated object that's sole purpose is to own a pointer and to decide when and how to delete it.
If this object allowed that same pointer to just get passed around wily-nily, without thought, then it simply could not serve its purpose. Any time you dig into a smart pointer to get at the raw pointer inside you violate its ownership semantics and must then take very careful care not to go doing something stupid. Smart pointers make you think about this by forcing you to make a call to get at the pointer inside rather than just silently doing so whenever you accidentally pass it to the wrong kind of function. Think of it like the smart pointer saying, "Hey, you know what you're doing can be dangerous, right? OK then, here you go."
IMHO, the universe would be a better place if shared pointers didn't allow access to their pointers. Unfortunately, that's not this universe and can't be this universe because occasionally you still need to pass that thing into a function that doesn't use smart pointers. So, since we don't live in that better universe, OUR smart pointers do allow access, they're just not sluts about it.
Perhaps there is a way, but it's kind a dirty one. You could try to put another class in your hierarchy: ABase. A could inherit from ABase, and ABase would contain default implementations of all the public methods. Something like this:
#include <iostream>
#include <boost/shared_ptr.hpp>
class ABase
{
public:
ABase() {}
void init( ABase *a ) { mImpl.reset( a ); }
virtual void setX( int x ) { mImpl->setX( x ); }
virtual int getX() const { return mImpl->getX(); }
boost::shared_ptr< ABase > mImpl;
};
class A : public ABase
{
public:
typedef ABase BaseClass;
A(int x) {mX = x;}
virtual void setX(int x) {mX = x;}
virtual int getX() const {return mX;}
private:
int mX;
};
template <class T>
class Shared : public T::BaseClass
{
public:
Shared(T* t) { init( t ); }
};
int main()
{
Shared< A > sh( new A( 1 ) );
std::cout << sh.getX() << std::endl;
sh.setX( 5 );
std::cout << sh.getX() << std::endl;
}
This is only a concept. I need to verify code. Key idea is to pass default implementation by inheriting shared not directly from type A, but from his base type, that has all implementations needed. Base class needs some more work, but I think the idea is pretty clear.
Its not exactly what you asked for (it's actually impossible), but it could be useful in some cases, and is probably closest you can get.
Putting aside whether or not this is a good idea. If you want a shared-pointer type that can be implicitly converted to a raw pointer, you don't need to inherit from the pointee type or go through other such complications. Just make a shared-pointer type with the appropriate implicit conversion operators.
This could be done through inheritance or composition of an existing shared pointer type. (Or else by making your own shared pointer from scratch).
Using inheritance, for example:
template<typename T>
class convertible_shared_ptr : public boost::shared_ptr<T>
{
public:
convertible_shared_ptr() {}
convertible_shared_ptr(T* ptr) : boost::shared_ptr<T>(ptr) {}
operator T* () const
{
return get();
}
T* operator-> () const
{
return get();
}
};
You then use such a thing like so:
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
class A // simple class for example purposes
{
public:
A() : member(42) {}
int member;
};
void foo(A* a)
{
cout << "a->member=" << a->member << endl;
}
int main()
{
convertible_shared_ptr<A> ptr(new A);
foo(ptr);
cout << "ptr->member=" << ptr->member << endl;
return 0;
}
Of course, I haven't actually tried such a thing in a real world scenario. There might be some complications when trying to interact with corresponding weak_ptr types. At the very least, there might be some more code necessary to cover all the possible usages.