What's the difference between doing,
EventList temp;
EventList* temp = new EventList();
Where now temp you access it's vars by doing using .
and the other is ->
Besides that difference, what else? Pointer allocates on the heap while just EventList is on the stack. So is it primarily a scope thing?
There is short summary
Object on the stack EventList temp;
access is little bit faster, there is no derefferencing
object are automatically deleted at the end of method which creates them so we don't have to care about their deletion
stack size is limited ( much more than heap )
these objects cannot be returned from the method without copying
Object on the heap EventList* temp = new EventList();
heap is "unlimited" ( comparing to stack )
these objects are easilly shared accross whole application because they aren't automatically deteled
we have to delete them manually, if we loose the pointer then there are lost bytes in memory ( leaks )
Eventlist temp is allocated and deallocated automatically within the scope in which it is called. That is, when you run the following code:
{
EventList temp;
}
The default constructor for EventList is called at the point of its declaration, and the destructor is called at the end of the block.
EventList *temp = new EventList(); is allocated on the heap. You can read more about it here.
Well, from that example, there are only things that you have noted that are differences, but when using virtual functions and inheritance you'll see differences.
For example, here is the same code with pointers and without:
WITH POINTERS:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Create()
{
cout <<"Base class create function ";
}
};
class Derived : public Base
{
public:
void Create()
{
cout<<"Derived class create function ";
}
};
int main()
{
Base *x, *y;
x = new Base();
y = new Derived();
x->Create();
y->Create();
return 0;
}
OUTPUT:
Base class create function
Derived class create function
WITHOUT POINTERS:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Create()
{
cout <<"Base class create function ";
}
};
class Derived : public Base
{
public:
void Create()
{
cout<<"Derived class create function ";
}
};
int main()
{
Base x, y;
x.Create();
y.Create();
return 0;
}
OUTPUT:
Base class create function
Base class create function
So there are problems with objects and virtual functions. It is executed base class function when derived one should be. That is one of differences.
Related
Consider the code below (note: after rightful criticism I reworded the question):
#include <vector>
using std::vector;
class DataSuper {
public:
DataSuper() {}
};
class DataSub : public DataSuper {
public:
int a;
DataSub() {}
};
class Super {
public:
DataSuper data;
Super() {}
};
class Sub : public Super {
public:
Sub(DataSub i) {
data = i;
}
void test() {
// I would like to print the value of data.a
}
};
int main(int argc, char *argv[]) {
DataSub dataSub;
Super* s = new Sub(dataSub);
s->test();
delete(s);
return 0;
}
Super has an instance of DataSuper called data. Sub, a subclass of Super, has the same object data, but it is an instance of DataSub, which inherits from DataSuper.
In essence, I would like to access data.a from class Sub. I know I can do it with having data as a pointer and then use dynamic_cast, but not sure if this is good practice.
Is there a way I can avoid it WITHOUT having data as a pointer?
Super::data isn't a DataSub, but you're treating it like it is one.
Remember, in C++ a variable of object type is the object. It is not a reference or a pointer or anything like that unless you declare it to be. Super::data is a DataSuper and it can never be anything else. Forcibly pointing a DataSub& at it like you have here will not end well.
If you want to share a DataSub between your Super and Sub classes you'll need to use a pointer. For example:
class Super
{
public:
std::unique_ptr<DataSuper> data;
Super(std::unique_ptr<DataSuper> data) : data{std::move(data)} {}
};
class Sub : public Super
{
public:
using Super::Super;
private:
// Use this if you need to treat data as a DataSub
DataSub& dataSub()
{
return static_cast<DataSub&>(*data);
}
};
int main()
{
std::unique_ptr<Super> s = std::make_unique<Sub>(std::make_unique<DataSub>());
}
Demo
If you want to avoid the extra allocation for data that this requires, you could reverse the ownership direction. That is, have Sub pass a non-owning pointer to a DataSub to Super's constructor and have Sub own the object:
class Super
{
public:
Super(DataSuper* data) : data{data} {}
private:
DataSuper* data;
};
class Sub : public Super
{
public:
Sub() : Super{&data} {}
private:
DataSub data;
};
int main()
{
std::unique_ptr<Super> s = std::make_unique<Sub>();
}
Demo
Note that this approach is slightly less safe than the first approach since Sub::data isn't yet initialized when Sub's Super subobject gets initialized. If you try to use the object pointed to by Super::data in Super's constructor you'll quickly wander into the land of undefined behavior. The same goes for Super's destructor. Sub::data gets destroyed before the body of Super::~Super gets executed, so attempting to access the object pointed to by data from Super's destructor body will also result in undefined behavior.
Hello everyone and thanks for reading,
I'm new to working with classes and I've ran into an issues with making array's of objects,
I have a base class, and an array of the same type, I'd like to know if it's a possibility to
make subclasses of the base class type and put them into an array and call methods that're not
in the base class, sorry if this is a bad question and my apologies if my wording is off,
#include <iostream>
int main()
{
BaseClass* ObjectList[10];
ObjectList[0] = new SubClass;
ObjectList[0]->Load(10);
ObjectList[0]->OtherFunction(); // How Can I Do This?
return 0;
}
class BaseClass
{
public:
virtual void Load(int Num) = 0;
};
class SubClass : public BaseClass
{
void Load(int Num) override
{
std::cout << Num << std::flush;
}
void OtherFunction()
{
// Do Something
}
};
Thanks
Edit -
My intent is to have a simple base class with dozens and dozens of subclasses with different methods, and have an array of the base class,
You can always have more than one pointer (or reference) to the same object.
int main()
{
BaseClass* ObjectList[10];
SubClass TheSubclass;
ObjectList[0] = &TheSubclass;
ObjectList[0]->Load(10); // presumably in a loop
TheSubclass.OtherFunction();
return 0;
}
You will have to downcast your pointer to the real class (or at least a class having the method). You can use either a static_cast if you do not need any control, or a dynamic_cast if you want a run-time validation of the cast:
...
SubClass *psc = dynamic_cast<SubClass *>(ObjectList[0]);
if (psc != nullptr) { // an invalid cast would set it to NULL
psc->OtherFunction();
}
else {
// process the error
}
After searching for hours, I end up here. I have a Container class with a pointer to Base class as member variable. This should either refer to Spec1 or another inherited classes of Base, which I omitted here. The type should be determined by the argument in constructor (e.g. string, enum, int, etc.).
I read much about dynamic memory allocation and why it should be avoided whenever possible. Is it possible to avoid here? Isnt any usual object destroyed after the constructor? Or is the design idea completely wrong? I come from Java :( Thanks in advance.
class Base{
public:
virtual ~Base(){}; // required?
virtual void doSomething() = 0;
};
class Spec1 : public Base {
public:
Spec1(){};
Spec1(int i){
// whatever
}
void doSomething(){
std::printf("hello world");
}
};
class Container{
public:
Container(String type_message){
if (type_message.compare("We need Spec1")){
m_type = new Spec1(1);
} // add more ifs for other types (Spec2, Spec3 etc.)
}
void doSomethingWithSpec(){
m_type->doSomething();
}
private:
Base* m_type;
};
int main (int argc, char **argv){
Container a ("We need Spec1");
a.doSomething();
}
Requiring Container to be aware of every possible derived class of Base does not sound like good design. That is what factory functions are for.
Have Container store that object as std::unique_ptr to avoid memory leaks and manual memory management.
struct Base {
virtual ~Base() = default;
virtual void doSomething() = 0;
};
struct Spec1 : Base {
void doSomething() override {
std::printf("%s\n", __PRETTY_FUNCTION__);
}
};
// Factory function.
std::unique_ptr<Base> createBase(std::string const& type) {
if(type == "Spec1")
return std::unique_ptr<Base>(new Spec1);
throw std::runtime_error("Unknown type " + type);
}
class Container {
std::unique_ptr<Base> m_type;
public:
Container(std::string const& type)
: m_type(createBase(type))
{}
void doSomething(){
m_type->doSomething();
}
};
int main() {
Container a ("Spec1");
a.doSomething();
}
Constructor works like any other function. Local variables are allocated in stack and get out of scope whenever the function completes whereas dynamic memory allocation is done in stack and needs to be explicitaly deallocated (in C++ and not in Java) before the function completes.
However in your case
m_type = new Spec1(1);
new Spec1(1) is dynamically allocated in heap and won't get destroyed on completion of Constructor code. The reference is stored in the member variable of the class. So as long as the instance of class Container is in scope, the memory allocated to Spec1(1) can be referred.
To compare just consider other scenario.
Container(String type_message){
Base* m_type;
if (type_message.compare("We need Spec1")){
m_type = new Spec1(1);
} // add more ifs for other types (Spec2, Spec3 etc.)
}
Here as soon as constructor finishes, m_type will go out of scope but new Spec1(1) will still be there in heap as the memory leak.
I am very much new to c++. I have a situation like: I have a base class which holds two virtual functions(NOT PURE). I have a derived class for this class where I implemented those virtual functions. Now in my main() function I created a pointer to pointer object to the base class. Now using this object how can I access the derived class object and functions.
I only want the pointer to pointer object of base class should be used to access derived class object.
BASE CLASS:
class another
{
public:
virtual void setName(){};
virtual string getName(){};
};
Derived Class
class use: public another
{
public:
string str;
void setName()
{
str = "USE CLASS";
}
string getName()
{
return str;
}
};
MY main() function:
int main()
{
another **an;
*an = new use();
an->setName(); //getting error
cout<<an->getName()<<endl; //getting error
return 0;
}
*an = new use();
Pointer an is not initialized, it cannot be dereferenced. Using doubled pointer (pointer to pointer) got no practical sense here. All tit does is to add another level of reference to code in this case. Expression that dereferences such pointer, results in value of pointer to class 'another', stored ... where? You had never created that storage, so such operation is an UB.
Legal variants of code:
int main()
{
another **an = new another*(); // creating storage for pointer
*an = new use();
(*an)->setName();
cout<<(*an)->getName()<<endl;
delete *an; // don't rely on OS to do so.
delete an;
return 0;
}
int main()
{
another **an = new another*(new use()); // doing this in one line
// storage of *an would be value-initialized by value returned
// from 'new use()' instead of default initialization
(*an)->setName();
cout<<(*an)->getName()<<endl;
delete *an; // don't rely on OS to do so.
delete an;
return 0;
}
int main()
{
another *an = new use();
// We don't need another pointer~ use an reference where required?
an->setName();
cout<<an->getName()<<endl;
delete an; // don't rely on OS to do so.
return 0;
}
PS. This declaration of class another technically is ill-formed, I may assume that you had skipped body of getName. It should cause compile time error about function's missing return value. If another is unusable class itself, you may declare methods as pure
class another
{
public:
virtual void setName() = 0;
virtual string getName() = 0;
};
An instance of such class or of a derived class that DOES NOT override those methods cannot be created, but it provides that "boilerplate" mechanics you're studying.
an is a pointer to pointer to another. *an returns a pointer to another. So you want (*an)->setName(); like so:
int main()
{
another **an;
*an = new use();
(*an)->setName(); //getting error
cout<<(*an)->getName()<<endl; //getting error
return 0;
}
I am new to c++ (I am using visual studio 2013) and I started experimenting with classes and inheritance. So I came up with a question which I can not find any anwser. Lets say we have this class:
#include <iostream>
using namespace std;
class base{
protected:
int var;
public:
void setvalue(int);
virtual void print();
};
class first:public base{
public:
void print();
};
class second: public base{
public:
void print();
};
Is there a way I can declare in my main() a pointer to base, set the value and after that choose if it is a first or second class? Ex:
int main(){
base *ptr = new base;
ptr->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
ptr->print(); // use the correct member, based on which class I choosed
return 0;}
Is this somehow possible? (As I said I am new to c++ so in case you have any questions, feel free to ask!)
Thanks!
Since it's not possible, the only thing that comes to mind is that you solve your problem in another way, perhaps using some well common design pattern.
In this case, given the little information you gave, Factory pattern seems appropriate.
#include <iostream>
using namespace std;
class base {
protected:
int var;
public:
void setvalue(int);
virtual void print();
static base* makeObject(int);
};
class first : public base {
public:
void print();
};
class second : public base {
public:
void print();
};
base* base::makeObject(int param) {
base* ret = NULL;
if(/* some condition based on params */) {
ret = new first();
ret->setvalue(0);
} else if(/* some other condition */) {
ret = new second();
ret->setvalue(1);
}
return ret;
}
int main() {
base *ptr = base::makeObject(...);
base->print(); // use the correct member, based on which class I choosed
return 0;
}
The type of an object is fixed at construction and can never be changed. So the direct answer to your question is "no".
But within that framework you have a lot of power. For example, you could separate your three classes out into four: three that do just do printing (BasePrinter, DerivedPrinter1, DerivedPrinter2) and other that just holds the value and doesn't have any virtual methods. Your BasePrinter class could get passed a ValueHolder object (by const reference) every time you call the print() method. Alternatively, each ValueHolder could have a pointer to BasePrinter object and pass in all the necessary data each time, with a little (non-virtual) print() method to do all this forwarding.
Not directly. When you create an object, you need to specify its full type so that C++ knows how to correctly lay out memory for you.
If you actually need to change it later, you can always create a new class (of the correct derived type) and use the original base class to initialize it, then delete the original. This might be slightly slower than the method you were proposing (depending on the final complexity of the class), but it would get the job done.
Since you are using inheritance , it is best practice to define virtual destructor in your base class. It will take care proper clean up when you define complicated class.
int main(){
base *ptr = new base;
base->setvalue(1);
/* Here I choose if base is pointing to First or Second class*/
base->print(); // use the correct member, based on which class I choosed
return 0;}
What you are trying to do is not possible. You have to change your program as follows to avoid compilation error.
base *ptr = new base;
ptr->setvalue(1);
ptr->print();
delete ptr;
return 0;
Because you base pointer ptr always have the dynamic type of class base. this code always invoke base::print function
If you define ptr as follows, you can utilize the polymorphism.
base * ptr = new first;
ptr->setvalue(1);
ptr-> print()
delete ptr
Here ptr has a dynamic type of class first and it will call function first::print()
You have to choose type at the creation of the object:
int main()
{
base *ptr = new first; // here.
ptr->setvalue(1);
ptr->print(); // use first::print.
delete ptr;
}