I have't coded in c++ for some time and I got stuck when I tried to compile this simple snippet:
class A
{
public:
void f() {}
};
int main()
{
{
A a;
a.f(); // works fine
}
{
A *a = new A();
a.f(); // this doesn't
}
}
It's a pointer, so instead try:
a->f();
Basically the operator . (used to access an object's fields and methods) is used on objects and references, so:
A a;
a.f();
A& ref = a;
ref.f();
If you have a pointer type, you have to dereference it first to obtain a reference:
A* ptr = new A();
(*ptr).f();
ptr->f();
The a->b notation is usually just a shorthand for (*a).b.
A note on smart pointers
The operator-> can be overloaded, which is notably used by smart pointers. When you're using smart pointers, then you also use -> to refer to the pointed object:
auto ptr = make_unique<A>();
ptr->f();
Allow an analysis.
#include <iostream> // not #include "iostream"
using namespace std; // in this case okay, but never do that in header files
class A
{
public:
void f() { cout<<"f()\n"; }
};
int main()
{
/*
// A a; //this works
A *a = new A(); //this doesn't
a.f(); // "f has not been declared"
*/ // below
// system("pause"); <-- Don't do this. It is non-portable code. I guess your
// teacher told you this?
// Better: In your IDE there is prolly an option somewhere
// to not close the terminal/console-window.
// If you compile on a CLI, it is not needed at all.
}
As a general advice:
0) Prefer automatic variables
int a;
MyClass myInstance;
std::vector<int> myIntVector;
1) If you need data sharing on big objects down
the call hierarchy, prefer references:
void foo (std::vector<int> const &input) {...}
void bar () {
std::vector<int> something;
...
foo (something);
}
2) If you need data sharing up the call hierarchy, prefer smart-pointers
that automatically manage deletion and reference counting.
3) If you need an array, use std::vector<> instead in most cases.
std::vector<> is ought to be the one default container.
4) I've yet to find a good reason for blank pointers.
-> Hard to get right exception safe
class Foo {
Foo () : a(new int[512]), b(new int[512]) {}
~Foo() {
delete [] b;
delete [] a;
}
};
-> if the second new[] fails, Foo leaks memory, because the
destructor is never called. Avoid this easily by using
one of the standard containers, like std::vector, or
smart-pointers.
As a rule of thumb: If you need to manage memory on your own, there is generally a superiour manager or alternative available already, one that follows the RAII principle.
Summary: Instead of a.f(); it should be a->f();
In main you have defined a as a pointer to object of A, so you can access functions using the -> operator.
An alternate, but less readable way is (*a).f()
a.f() could have been used to access f(), if a was declared as:
A a;
a is a pointer. You need to use->, not .
Related
I would like to use virtual functions of objects of different classes (derived from the same base class) without a) constructing all the objects or b) using new. Please see the code example:
#include <iostream>
class A{
public:
virtual void p(void){std::cout << "Im A" << std::endl;};
};
class B : public A{
public:
virtual void p(void) override {std::cout << "Im B" << std::endl;};
};
class C : public A{
public:
virtual void p(void) override {std::cout << "Im C" << std::endl;};
};
int main(){
bool cond = true; // some condition
A* o1;
if (cond) o1 = new B(); else o1 = new C();
o1->p(); // will call correct p(), i.e. either B::p or C::p but not A::p
A o2 = B();
o2.p(); // will call A::p
A* o3;
B tmp1; C tmp2; // construct both objects altough only one is needed
if (cond) o3 = &tmp1; else o3 = &tmp2;
o3->p(); // will call correct p(), i.e. either B::p or C::p but not A::p
A* o4;
if (cond) {B tmp; o4 = &tmp;} else {C tmp; o4 = &tmp;} // uses address of local variable
o4->p(); // will call correct p(), i.e. either B::p or C::p but not A::p
return 0;
}
I want the behavior of o1 but without calling new. o2 doesnt work (calls function of base class and if base class is abstract it doesnt work at all). o3 works but constructs all the different objects although only one is needed. o4 kinda "works" but uses a reference to a local variable outside of its scope.
What would be the correct / best / modern C++ way to do it?
It will be better to use a helper function when you want to avoid using new but be able to use different derived types based on some condition.
void do_stuff(A& obj)
{
}
int main()
{
bool cond = true; // some condition
if (cond)
{
B tmp;
do_stuff(tmp);
}
else
{
C tmp;
do_stuff(tmp);
}
return 0;
}
How to use virtual functions in derived objects without new
Like this:
B b;
C c;
A& a = cond ? b : c;
a.p();
without a) constructing all the objects
You can also do this:
if (cond) {
B b;
b.p();
} else {
C c;
c.p();
}
At this point it doesn't really matter that the function is virtual though since we are using static dispatch. Which is better than dynamic dispatch.
o4 kinda "works" but uses a reference to a local variable outside of its scope.
I.e. the behaviour of the program is undefind i.e. it doesn't work at all.
If using placement new is acceptable, you can use a union to hold the storage, then construct the proper member based on the condition:
union U {
U() { }
B b;
C c;
};
int test(bool cond) {
U u;
A *a2;
if (cond)
a2 = new (&u.b) B;
else
a2 = new (&u.c) C;
a2->p();
return 0;
}
The constructor in the union is necessary since the default constructor will be implicitly deleted due to the presence of non-trivial default constructors for the members of the union.
You'll also have to manually destroy your objects when you're done.
For starters this code snippet
A* o4;
if (cond) {B tmp; o4 = &tmp;} else {C tmp; o4 = &tmp;} // uses address of local variable
o4->p(); // will call correct p(), i.e. either B::p or C::p but not A::p
has undefined behavior because outside the if statement the pointer o4 is invalid due to the fact that the local object tmp is not alive outside the scopes of the if sub-statement.
As for this code snippet
A o2 = B();
o2.p(); // will call A::p
then you should use a reference to an object of the type B. For example
B b;
A &o2 = b;
o2.p();
As for the code snippet with the pointer o1 then in any case pointed objects must exists. Either they will be created dynamically as in your example or you can create the both locally and then depending on the condition set the pointer to one of them.
If you're worried about using new because of memory management, just use a std::shared_ptr instead:
int main(){
bool cond = true; // some condition
std::shared_ptr<A> o1;
if(cond) {
o1 = std::make_shared<B>();
} else {
o1 = std::make_shared<C>();
}
o1->p();
return 0;
}
Prints:
Im B
Working example
Note: I was originally going to suggest an std::unique_ptr instead, however I didn't think they were copyable. But I was wrong. std::unique_ptrs will work too.
Note 2: you will need C++14 or later to use std::make_shared() or std::make_unique, but new will work in C++11. That violates your rule of not using new, but at least it does manage memory for you.
If you want to avoid new mainly to avoid the extra cleanup code and potential bugs from dangling pointers, double deletes, etc., just use std::unique_ptr:
std::unique_ptr<A> o1;
if (cond)
o1 = std::make_unique<B>();
else
o1 = std::make_unique<C>();
o1->p();
This will do essentially the same as the code using new, but behind the scenes, and also does the delete for you when o1 goes out of scope.
If you have a performance-critical code bottleneck and want to avoid the overhead of the heap memory allocation and deallocations used by new, things get trickier, but you could do it with something like:
using B_or_C_type = std::variant<B,C>;
auto o5 = cond ? B_or_C_type{B{}} : B_or_C_type{C{}};;
std::visit(std::mem_fn(&A::p), o5);
On typical systems, this code will avoid using any heap memory at all, instead using stack memory large enough to hold the larger of B or C. std::variant has the logic to act like a union but making sure only the correct type actually gets used. std::visit applies any functor to a variant, as long as the functor can be called with every type in the variant. Note if you define a variant variable with no initializer, it creates an object with the first type, though it can be reassigned to a different-typed object later. (If creating that default object isn't possible or should be avoided, you could use std::monostate as the first dummy type - but then using std::visit gets trickier.)
My code is like following, basically I am using some external library and embed some class objects from this library to myClass, then do things with OBJ,
#include "extern_lib.h" //some library
class myClass
{
public:
extern_class *obj1;
extern_class *obj2;
double arr[3];
};
int main()
{
myClass *OBJ= new myClass();
OBJ->obj1 = new extern_class(arg1...);
OBJ->obj2 = new extern_class(arg2...);
//do something like
OBJ->obj1->extern_fun1(arg1...);
OBJ->obj2->extern_fun2(arg2...);
//delete
delete OBJ;
return 0;
}
I would like to know,
1- in order to free all the objects, is it enough to delete OBJ?
2- is there better ways to write this code?
No, it is not enough. You have to call delete for every new you place in your code explicitely.
Use smart pointers like std::unique_ptr or better, use RAII. To clarify that: smart pointers and RAII are not even only better ways of doing so, they are the ways of doing it correctly in modern C++.
Here's an adequate example with RAII:
#include "extern_lib.h"
class myClass
{
public: // note that public members are possibly bad design (depending on your situation)
extern_class obj1;
extern_class obj2;
double arr[3];
};
int main()
{
myClass foo;
foo.obj1.extern_fun(arg1...);
foo.obj2.extern_fun(arg2...);
return 0;
}
Please note that it's not possible to use RAII in every situation. If you run into such, use smart pointers as stated:
#include "extern_lib.h"
class myClass
{
public: // note that public members are possibly bad design (depending on your situation)
std::unique_ptr<extern_class> obj1;
std::unique_ptr<extern_class> obj2;
double arr[3];
};
int main()
{
myClass foo;
foo.obj1 = std::unique_ptr<extern_class>(new extern_class(arg1...));
foo.obj2 = std::unique_ptr<extern_class>(new extern_class(arg2...));
foo.obj1->extern_fun(arg1...);
foo.obj2->extern_fun(arg2...);
return 0;
}
In order to free all the objects, is it enough to delete OBJ?
No, this will produce a resource leak as the (default) destructor of myClass doesn't care about deleting the pointer members.
Is there better ways to write this code?
Yes, use smart pointers. For example:
class myClass
{
public:
std::unique_ptr<extern_class> obj1;
std::unique_ptr<extern_class> obj2;
double arr[3];
};
In general, try to make resources owned by classes. That is, allocate them in the constructor and deallocate them in the destructor. The standard library's smart pointers will already do that job for you. Avoid managing more than one resource inside a single class.
By the way: If your example is not contrived and you are really not using polymorphism at all, then just get rid of all those news and simply use variables with automatic storage duration. C++ is not Java.
Update: Here is (one way of) how to get rid of new if polymorphism is not needed:
class myClass
{
public:
extern_class obj1;
extern_class obj2;
double arr[3];
myClass(type arg1a, ..., type arg2a, ...) : obj1(arg1a, ...), obj2(arg2a, ...)
// ^^^^ member initializer list ^^^^
{
}
};
The key is to create the member objects as part of the process of creating myClass by using a so-called member initializer list. If you are programming C++11, prefer writing obj1 {arg1a, ...}, obj2 {arg2a, ...} for consistency. (The old syntax still works equally well, however.)
Likewise in your main function:
int
main()
{
myClass mc(arg1a, ..., arg2a, ...); // (1)
mc.obj1.extern_func(...);
mc.obj2.extern_func(...);
return 0; // (2)
}
At line (1), we create an instance of myClass on the stack using our new constructor that will create the members obj1 and obj2 correctly. The compiler-generated default constructor of myClass will correctly destruct mc.obj1 and mc.obj2 as mc goes out of scope on line (2). Again, in C++11 line (1) can be written more cleanly as myClass mc {arg1a, ..., arg2a, ...};.
class A
{
public:
A* operator->() const
{
}
void Test() {}
};
then call it like this.
A* a = new A;
a->Test();
The code builds and runs successfully in VC2010. It seems very strange. I am wondering it is by design or it is a bug of VC2010?
Thanks
You aren't calling your operator-> in your example, you are calling Test directly from an A*. You want:
(*a)->Test();
Or...
A a;
a->Test();
There's nothing wrong with VS2010 concerning operator-> (that I know of).
Using -> on a pointer named a effectively executes: (*a).. Using -> on a variable by value will invoke your operator-> if present, or be a syntax error if there is no operator->.
Your code is:
A* a = new A;
a->Test();
The "a" is a pointer to an A. It is NOT an A object itself, it is a memory address of the A object on the heap.
When you call a->Test() you invoke the pointer's -> operator (built in for all pointer types in C++). You would have to do this to invoke your operator:
//Create an A (NOT a pointer).
A a;
//Invoke the A's operator ->
a->Test();
Which is how STL iterators work - they're class types, not pointers to class types. Note that the return type of operator -> must make sense for the operation/member you're trying to invoke.
So, here's an example that would call test via the ->:
#include <iostream>
class A
{
public:
A* operator->()
{
return this;
}
void Test() { std::cout << "Hello World!"; }
};
int main()
{
A a;
a->Test();
}
It's strange, but it works because a->Test(); returns the current object, which Test() is then called on (see the return this; line).
See STL iterators for useful examples of why you'd actually want to do this.
So one rule of thumb I've heard with respect to modern C++ style is that one shouldn't need to use new or delete, and one should instead use smart pointers. So how to go about this when I have a class where one of the members is a pointer to another object. By using a smart pointer I can avoid the need to delete, but I still need to create the object with new. E.g. is the below "canonical" modern C++ style, or how should one go about this?
#include
#include
class B {
public:
B () { std::printf("constructing B\n");}
~B () { std::printf("destroying B\n");}
};
class A {
public:
A ()
{
std::printf("constructing A\n");
b = std::unique_ptr(new B());
}
~A () { std::printf("destroying A\n");}
private:
std::unique_ptr b;
};
int main()
{
A a;
return 0;
}
You use new. There's nothing wrong with using new, it should just be used as rarely as possible.
(delete on the other hand, should almost never be used, since its usage should always be encapsulated in some sort of RAII handle like a smart pointer or a container.)
Note that when using smart pointers, you should always assign the result of new to a named smart pointer or use reset. In your case, you'd want to use:
A() : b(new B()) { }
or:
A()
{
std::unique_ptr<B> x(new B());
b = std::move(x);
}
or:
A() { b.reset(new B()); }
(For why this is important, see the "Best Practices" section of the boost::shared_ptr documentation.)
I need the flexibility of being able to change parameters passed around to different functions, depending from where the call to the function happened, so I decided I'd put all my parameters in a struct, however most of these parameters are structs or classes themselves and I want to have the option of leaving them NULL, so I have to pass pointers to the structs/classes.
struct A
{
otherB* b; // NULL should be a valid value
otherC* c;
};
However my question is now, passing A around these pointers will be the only thing copied, so if I did the following there would be a problem right?
void func(A& a) //non const cause I wanna change contents of A.
{
a.b = new b();
}
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA); //myA goes out of scope? so I've lost all pointers assigned and since somec is out of scope too, I have a problem?
What would the best way to resolve something like this+ I want the flexibility of being able to pass NULL to any of my parameters, however not sure if using raw pointers everywhere is a good idea?
To solve the problem of resource management, you should use boost::shared_ptr (or std::shared_ptr in C++0x).
struct A
{
boost::shared_ptr< otherB > b;
boost::shared_ptr< otherC > c;
};
void func(A& a)
{
a.b = boost::make_shared< otherB >();
}
A myA;
otherC somec;
myA.c = boost::shared_ptr< otherC >(&somec, null_deleter());
func(myA);
When myA goes out of scope, all resources are deallocated automatically. Since somec was allocated on the stack, we wrapped it in a shared_ptr that uses a null_deleter, that could look like this:
struct null_deleter {
void operator()(void *) { }
};
This will not delete the object, it will do nothing (which is just what we want for stack-allocated objects). Keep in mind however, that you have to make sure that somec lives longer than myA, otherwise you will get access violations.
boost::optional<> Allows you to test if the field is set or not.
Simple example (will not compile, I've not even remotely tested it, in theory this is how it should work)
struct params
{
boost::optional<int> a;
boost::optional<foo> b;
boost::optional<bar> c;
};
void func(params& p)
{
if (p.a)
{
// do stuff with a
}
if (p.b)
{
// do stuff with b
}
if (p.c)
{
// do stuff with c
}
else
p.c = bar(); // again copy constructed and now initialized...
}
params p;
p.a = 1;
p.b = foo(); // copy constructed, however you can store a reference in the optional too.
// c is uninitialized
func(p);
// when p goes out of scope, everything is gone..
You basically have to analyze ownership, i.e. who can allocate and who is responsible for deleting object once they no longer is used.
One thing that is important to remember is that if you mix dynamically allocated things and things placed on the stack, you simply can't apply delete on them, as it's not possible to delete things on the stack.
One way could be to only use new and define a destructor in A that deletes all it's pointers. Another way could be a place where you would register objects that later should be deleted. Or you could go the route of using existing reference-counting tools, as suggested in other answers.
No, your idea of the scope of myA and somec are wrong. There's nothing wrong with what you have right now- although I personally think that references would be a superior option to pointers.
void func(A& a) //non const cause I wanna change contents of A.
{
a.b = new b();
}
int main() {
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA);
// myA and somec are still perfectly in scope to be saved, or deleted, or w/e as you like
}
It's not clear from your description, but if you're having a problem
because somec is going out of scope, it can only be because func is
saving a copy of the pointer. Don't do that: in funct, copy the object,
not the pointer.
PS: if most of the pointers are null most of the time, you should
consider using something like following syntactic sugar:
struct A
{
// pointer members...
A() : // ... set all pointers to null...
A& withB( B const& someB ) { otherB = &someB; return *this ; }
A& withC( C const& someC ) { otherC = &someC; return *this ; }
// And so on for all of the rest of the pointers.
};
func( A().withC( somec ) );
Don't know if it's appropriate for your situation, but it's often
convenient.