class a
{
private:
b *b_obj;
public:
void set(int);
};
a::a()
{
b_obj = new b;
}
a::set(int s)
{
b_obj->c = s;
}
class b
{
public:
int c;
};
is this code valid?
if no, how do i make b_obj of a particular object (say a_obj) of class a ,modifiable in another class c...if a_obj i created in another class d....i am scared of a_obj going out of scope in class c.
hope you understand my question.
thanks a lot for taking the time to read my post
The code is nearly valid. class b needs to be declared (or at least forward declared) before it is referred to in class a, you do not specify the return type in the definition for a::set, and you have not provided a declaration for a'a default constructor. Here is the revised code, along with a test harness:
class b
{
public:
int c;
};
class a
{
private:
b *b_obj;
public:
a();
void set(int);
};
a::a()
{
b_obj = new b;
}
void a::set(int s)
{
b_obj->c = s;
}
int main()
{
a my_a;
my_a.set(42);
}
Now, just because the code is valid doesn't mean it's good:
You don't initialize c when default-constructing b.
You use raw pointers to dyanamically-allocated b's. Use automatic variables instead, whenever possible. Among the the reasons for this are ...
You never delete the b you new'ed in a'a constructor. This results in a memory leak. If you had avoided the use of dynamic allocation in the first place, this would not be an issue.
Well,
*b_obj = *other_b_obj;// equality of objects values
b_obj = other_b_obj; // equality for pointer values
assuming that b_obj is an object and other_b_obj is a pointer:
b_obj = *other_b_obj;
Assuming the reverse:
b_obj = &other_b_obj;
Assuming both are pointers:
b_obj = other_b_obj;
for your final question, new is not compulsory for assgining pointers. A pointer may point to an exiting object. However, if you want the pointer to point to a new object, use then new keyword, which attempts to create new object and returns the new object address.
is this code valid?
The code is almost valid, except that you forgot to state the return type of the set function:
void a::set(int s)
However, the set function will really change the c member of b_obj. It is public, so the compiler will allow it.
BTW, why don't you try for yourself?
As an aside, while you're studying, look at constructors, destructors, assignment operator and implement them to free the object b_obj properly. You can even use a shared_ptr for that.
Also, I wouldn't advise you to use such a dull name as lowercase a for a class.
Related
I have two classes A and B, in which the class B looks like
B.h
class B
{
public:
B();
virtual ~B();
void eval(int a, int b);
private:
A* APointer;
};
and correspondingly I have
B.cpp
B::B():APointer(NULL){}
B::~B(){}
void B::eval(int a, int b)
{
if a == b
{
APointer->run(); // run() is a public method defined in class A
}
}
Then the class A is like:
A.h
#include "LuaBridge.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
using namespace luabridge;
class LuaParser
{
public:
LuaParser(lua_State* L);
virtual ~LuaParser();
void run();
private:
LuaRef mRun;
LuaRef mStop;
lua_State* mL;
};
And
A.cpp
LuaParser::LuaParser(lua_State* L) :mRun(L),mStop(L),mL(L) {}
LuaParser::~LuaParser(){}
void LuaParser::run(){
std::cout<<"This project runs!"<<std::endl;
}
The system is complicated and actually I call this eval function in class C member function. In that class I define a private member BPointer by B* BPointer and in constructor I did C(B* BPointer = NULL) and then I simply use BPointer->eval(a,b) in a class C member function.
In my main code, I define a pointer in class B like B* BPointer and I use this pointer to call the method B::eval by
BPointer -> eval(a, b);
However, as I run it step by step in visual studio, at the command line APointer->run(); I noticed that the this pointer is like:
Value: 0xcdcdcdcd{APointer=???}
And when I tried to run this command, I got an error:
Access violation reading location 0xCDCDCDD1.
Well...I don't know how to solve this problem, what I wanna know is:
Is the whole idea (i.e. use a private object to call function of another class in a method of this class) feasible?
If this idea is feasible, then how should I modify my code?
Any suggestion or idea would be more than welcome!
Is the whole idea (i.e. use a private object to call function of
another class in a method of this class) feasible?
Yes, it's pretty common.
If this idea is feasible, then how should I modify my code?
You need to understand the difference between an object and a pointer. Pointer is an address of memory region which may even be unallocated.
What you have here is two pointers not pointing to any allocated memory, hence there are no objects whose methods you could possibly call.
BPointer is unitialized, it contains address of random memory region (or magic number 0xcdcdcdcd in debug build) which may contain just anything belonging or not belonging to you. Dereferencing it is undefined behavior. To avoid that, you should create B object and assign it's pointer to BPointer:
B *BPointer = new B;
After you're done making use of BPointer, you should release the memory and call B's destructor by calling
delete BPointer;
APointer is initialized with NULL pointer, which means it doesn't point to any memory region. Dereferencing NULL is undefined behavior too. Similarly to BPointer, it should be initialized with valid object pointer and released later:
B::B() : APointer(new A(/* lua state pointer */ NULL)) {}
B::~B() { delete APointer; }
If you don't necessarily need a pointer, I'd suggest using stack allocation for B and store A as plain member (not pointer). This way you won't need to bother with pointer initialization and deletion.
B.h
class B
{
public:
B();
void eval(int a, int b);
private:
A AObject;
};
B.cpp
B::B() : AObject(/* lua state pointer */ NULL) {}
void B::eval(int a, int b)
{
if (a == b)
{
AObject.run();
}
}
main.cpp
// ...
B b;
b.eval()
// ...
0xcdcdcdcd
is the state of allocated, but not yet initialized memory. Did you instantiate your BPointer in an appropriate way? For example
BPointer = new B();
Beyond that your APointer is NULL so you cannot call any methods like
APointer->run();
before you construct an object of type A and assign it to APointer as well.
You must initialize APointer data-member with some real object in constructor of class B. It should look something like below,
B::B()
{
this->APointer = new A();
}
B::~B()
{
delete this->APointer;
this->APointer = NULL;
}
...
...
int main()
{
B* BPointer = new B();
int x = 5;
int y = 5;
BPointer->eval(x, y);
}
In code you mentioned above, APointer is initialized to NULL. I think when B::eval() is executed, It will cause some undefined behavior.
It would be good if you can also post code of class A.
And again a bad-formulted question, but I don't know how to shortly explain this situation:
I have two classes. Let's name them A and B. A has a lot of member variables and methods. B is a struct which has a shared_pointer to an object of type A. Now A has a method that returns an instance of B (with a pointer to the current instance of A).
My problem is, that A is the subclass of C. C has the same method as described above as pure virtual. The code would look like this:
class C {
public:
virtual B mymethod() const =0;
virtual int getMyvar() const =0;
};
class A : public C {
public:
B mymethod() const override;
int getMyvar() const override; //outputs myvar
private:
int myvar;
};
struct B {
std::shared_ptr<C> pointer;
};
B A::mymethod() const {
B instance;
instance.pointer = std::make_shared<A>(*this); //is this wrong?
return instance;
}
My compiler (gcc 4.8.2) creates the executables for the following code, but at runtime I get "Segmentation fault (core dumped)":
void AnotherClass::something() const {
A object;
B instance = object.mymethod();
std::cout << instance.pointer->getMyvar(); //dumps the core womehow?
}
I read about the std::enable_shared_from_this but I could not figure out how it works or if it helps me.
Why do I get the error message and how can I fix this?
From what I have read in the manual, you do:
class A : public C, std::enable_shared_from_this<A> {
public:
B mymethod() override; // Notice the lack of const
private:
int myvar;
};
and then:
B A::mymethod() {
B instance;
instance.pointer = shared_from_this(); // this should be right
return instance;
}
Like this, all the instances of a std::shared_ptr to the same A object will share the same reference counter, and it will be destroyed only when it must be.
EDIT:
Also, notice that your object A must be managed by some other std::shared_ptr before you can call A::mymethod(). I.e. you must create A objects like this:
std::shared_ptr<A> a_obj(new A);
then you can call A::mymethod():
B b_obj = a_obj->mymethod();
EDIT2:
Method A::mymethod() (and consequently, C::mymethod()) can't be const to be able to call the non-const method shared_from_this().
Preliminary problem: how do you down-cast to access myvar ?
Edit: after your edit, this first topic is no longer relevant. I leave it because I used this code in the live demos illustrating how to solve it.
First, the statement that causes the dump can't compile as you gave it:
std::cout << instance.pointer->myvar;
because instance.pointer is a shared_ptr<C> and C has no member myvar.
If downcasting properly with dynamic_pointer_cast<A>(instance.pointer)->myvar (supposing AnotherClass is a friend) it works.
Your shared pointer made a clone: is it your intent ?
This statement:
instance.pointer = std::make_shared<A>(*this); //is this wrong? PERHAP'S !?
creates a clone object obtained by copy construction from *this. So you don't reference the original object A, and hence you don't need std::enable_shared_from_this : the use count of instance.pointer will be 1 because at that moment there's only one reference to the newly created shared object.
Live demo
Or do you want it to reference the original object ?
You then have to change the statement to:
instance.pointer = std::shared_ptr<A>(this); //better ?
But this won't compile because mymethod() is const, so it consider this as being a pointer to const. To compile the statement you must either remove the constness of mymethod() or add constness to B's pointer.
Then it works. B's shared pointer has still a use count of 1, which is again ok. But once this shared_ptr gets out of scope, the use count is 0 and the shared_ptr's destructor will try to delete the object. AS IT WAS INITIALY A LOCAL OBJECT (ON STACK) this causes a runtime error.
Final approach
As you want to have shared pointers to your object, the code of AnotherClass should be something like:
shared_ptr<C> pobject(new A); // create the object from the free store
B instance = pobject->mymethod();
...
And the C class must inherit as follows:
class C : public std::enable_shared_from_this<C>
{...}
And the my method class must initialize the shared_pointer it retures as follows:
//instance.pointer = std::shared_ptr<A>(this); // no, don't do no longer !!
instance.pointer = shared_from_this(); //<===== RETURN A POINTER TO SELF
Then everything works perfectly.
Live demo
It seems to me that you would get a memory error when your objects go out of scope.
When you create your object A and then create your shared_ptr with the this pointer, your counter will be 1 instead of 2 (as you would maybe expect). So A will be destroyed twice, instead of once.
A more correct way of doing this would be create class A as a shared_ptr and initialize the pointer in class B with it (not inside class A). This way the counter will be incremented as you expect and A will be deleted only once.
The class you want to share will need to inherit from enable_share_from_this.
Then you can call share_from_this to obtain a shared pointer to the class you're in.
If you just try and make_shared you just create a separate ownership group that will mean two things will try and delete your object. That will be the cause of your segfault.
Due to a mistake when designing an interface, a third-party software provider deleted a function, like the copy constructor in class base_noncopy_base:
class base_noncopy_base {
base_noncopy_base(const base_noncopy_base&);
public:
base_noncopy_base() {}
};
That class is supposed to be inherited, like:
class base_noncopy_derived : public base_noncopy_base {
// whatever ....
};
But now, it is no longer allowed to use base_noncopy_derived as a base_noncopy_base:
int main() {
base_noncopy_derived d;
// base_noncopy_base b1 = d; // won't compile
// base_noncopy_base b2(d); // won't compile
// base_noncopy_base b3((base_noncopy_derived)d); // won't compile
}
It is possible to const_cast a const member, and I have seen some hacks out there to access private members from outside a class, of course, only to be used in emergency cases. I am wondering: would there be any possibility of hacking the deletion of a function out?
Edit 1:
Elaborating further the question:
The actual problem arises from other third-party functions functions, like:
void base_noncopy_function1(base_noncopy_base &b) {
}
void base_noncopy_function2(base_noncopy_base b) {
}
I can use something like:
base_noncopy_base *b4 = &d;
base_noncopy_function1(*b4);
But not
base_noncopy_function2(*b4);
If you want to "use base_noncopy_derived as a base_noncopy_base", then use a reference or pointer rather than creating a new object:
base_noncopy_derived d;
base_noncopy_base & b = d;
Your commented-out code attempts to slice the base class, creating a new object by copying just part of d. This is rarely a sensible thing to do, and the reason why base classes tend to be abstract or non-copyable.
If you really want to do this, then you'll have to change the definition of the base class so that it doesn't delete the copy functions. There's no way to "undelete" them.
This is the closest things I could find to a possible duplication. However, the answers left me with questions still.
Here is a code sample:
class A {
A() {}
virtual void print() = 0;
}
class B : public A {
B() {}
void print() { printf("B"); }
}
class C : public A {
C() {}
void print() { printf("C"); }
}
int main() {
A** n;
n = new A*[4];
n[0] = new B;
n[1] = new C;
n[2] = new B;
n[3] = new C;
for(int i = 0; i < 4; i++)
n[i]->print();
printf("\n");
delete n[0];
delete n[1];
delete n[2];
delete n[3];
delete [] n;
}
With this bit of code you get "BCBC". Is there a way to change the derived class type without allocating a new object? Something like:
n[2] = (C*)n[2];
So that when you print the array out you now get "BCCC". I read in the linked post that having to do this is evidence of poor design. If that is the case, could that be explained? This seems like it would be a normal and frequent use case for object oriented design to me. Assume that all attributes are defined in the base class. The only difference in the classes are in the implementation of methods.
If C++ does not support changing an objects type like this at run time, what is the accepted way to achieve similar results?
Closest thing would be to implement in B and C constructors that will accept A(or A*) as input and copy any data need into new object. Then you should get something like this.
A* temp = n[2];
n[2] = new C(A);
delete temp;
But even better solution would be to create class that will hold data and A* pointing to a class implementing different ways of data manipulation.
The object pointed to by the pointer n[2] is a B object. It can't be magically changed into a C object. If you want a C object, you're going to have to create one. However, don't forget to delete the existing B object.
delete n[2];
n[2] = new C;
I don't believe that you can cast from class B to class C. Both of theses classes are also Class A, as in B is an A and C is an A however B is not a C and C is not an B. Either could be cast into A but this is a dangerous practice because of the slicing problem. In this case you have no data in the derived classes to be lost by casting so you aren't losing anything. However you don't need to cast a B or a C into an A in order to call the parent classes methods.
It would perhaps be possible to write a function that took a B object as input and returned a C object and a function that took a C object and returned a B object, but you would have to do all the work yourself manually converting one into the other.
You can't really change the type of object once it's created. But it doesn't mean you can't change behavior in run time. What you need to do is refactor your code.
class A;
class ImplA
{
public:
void print (A&) = 0;
};
class A
{
std::unique_ptr<ImplA> impl;
public:
A (ImplA* ia) : impl(ia)
{}
void print()
{
impl->print(*this);
}
void changeImpl (ImplA* ia)
{
impl.reset(ia);
}
};
This is of course using C++11's smart pointers, but the idea is the same regardless. You apply the fundamental theorem of software engineering: abstract the thing that changes.
I recommend you read up on design patterns. It will arm you with ideas to do the things you want without breaking the way OOP works.
i am pretty sure this is a simple question for a long time c++ user, this should be a pattern or the problem should be solved in any other way but given i am Python developer and a total novice with c++ i don't know how it's usually done.
Suppose that i have a class where i want to store a pointer to an object that can be of 1 of two different classes that respects an interface, for example:
class AllPlayers
{
public:
virtual void play();
};
class VlcPlayer: public AllPlayers
{
public:
virtual void play();
};
class Mplayer: public AllPlayers
{
public:
virtual void play();
};
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
VlcPlayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
else {
Mplayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
}
MyMediaPlayer test(0);
test.play();
First, i know this would not work and that it seems pretty normal why but how could i get this effect? i would like to have a member of a class for what i am going to use ever the same methods, implemented using a interface and i would like to avoid trying to cast to every of the derived classes every time i am going to use one of his methods.
C++ is value-based, i.e., if you create an object of a given type you really have an object of this type. This doesn't play nicely with dynamic polymorphism. To get dynamic polymorphism you use a pointer or a reference to the actual object. To also get the life-time straight you typicslly allocate the corresponding object on the stack (make sure your base class has a virtual destructor if you ever release an object of a derived type using a pointer to the base). With this, you should be all set: just call a virtual function of the base class through a pointer to rhe base: When you overridethe function in the derived class this is the function which is called.
If you write
AllPlayers m_player;
that is going to be an instance of AllPlayers and cannot be an instance of a class that derives from it.
You should instead use a pointer and allocate the class on the stack.
For example:
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
~MyMediaPLayer();
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
m_player = new VlcPlayer;
}
else {
m_player = new Mplayer;
}
}
MyMediaPlayer::~MyMediaPlayer()
{
if (0 != m_player) {
delete m_player;
m_player = 0;
}
}
As suggested by #xception use of unique_ptr may relieve you from having to write code to deallocate the instance.
As correctly pointed out by #DietmarKühl you should always declare a virtual destructor in a root class (a base class that does not itself derives from some other class) as is the case with AllPlayers.
class AllPlayers
{
public:
virtual ~AllPlayers();
virtual void play(); // note: this should probably be pure virtual.
};
The reason this will not work is colloquially known as Object Splicing. (Or, for those Harry Potter readers out there, Object Splinching)
Let's look at an example:
class Foo
{
public:
int bob;
float fred;
// Foo(const Foo& otherfoo); // implicit copy constructor
};
class Bar : public Foo
{
public:
double gabe; // gabe newell is fat
char steve; // steve jobs is thin
// Bar(const Bar& otherbar); // implicit copy constructor
};
int main()
{
Foo f;
Bar b;
f.bob = 10;
f.fred = 1.5;
b.bob = 15;
b.fred = 2.5;
b.gabe = 1.77245385091; // sqrt(pi)
b.steve = -4;
f = Foo(b);
return 0;
}
This is legal and valid. Problem is, the implicit copy constructor of Foo is called, and Foo's copy constructor knows nothing about what a Bar is. Only that it contains everything a Foo has, and some extra irrelevant crap. Because of this, only the Foo's data gets preserved; the data unique to the Bar gets spliced off.
It's important to note that this is DEFINED BEHAVIOR: it's doing EXACTLY WHAT YOU TELL IT TO. Casting between a subclass of a base class and a base class is implicit. Furthermore, the behavior of the copy constructor is implicit.
It's also important to note that, under the hood, C++ pointers and references work in the same way. It's perfectly sane to pass the Bar to Foo's copy constructor by reference, this pass by reference does not produce a copy of the object. It's the same as working with a pointer.
The actual splicing takes place as a direct result of the copy constructor biting off more than it can chew. It gets an object with more state than it expected, and its only choice is to ignore the extra state.
With python, this doesn't happen because everything is implicitly stored as a reference type. Since you only work with references (the objects themselves are abstracted away), you never have the opportunity to accidentally splice an object.