PDA

View Full Version : How to just declare class instance?



arcull
29th June 2015, 20:44
Hi everyone.

Apologies, if this sounds a bit dumb, but I just can't figure it out....Suppose I want to declare an instance of a class without creating it i.e. calling it's constructor. Let's say I have a gui desktop app and would like to declare instance of class on some gui show up event and make it public, well actually visible to other methods inside same gui. How would I do that? I mean something like pseudo bellow:

class Car {
public:
Car(int a, int b) {
//some code
}
SetColor(int clr) {
//some code
}
}

//code on mainwindow.cpp
Car Fiat; //<-but just declar it, don't create it

void MainWindow::Method1(int start,int end) {
Fiat...<- call constructor here
}

void MainWindow::Method2(int color) {
Fiat.SetColor(color);
}

anda_skoa
29th June 2015, 21:26
You do that by instantiating the object on the heap, i.e. using the new operator

https://en.wikipedia.org/wiki/New_(C++)

Cheers,
_

arcull
29th June 2015, 22:04
You do that by instantiating the object on the heap, i.e. using the new operator

https://en.wikipedia.org/wiki/New_(C++)

Cheers,
_ Thanks, yes you are right :( So I should first declare a pointer to my class and then create the instance of object on the heap with new operator. Would this work:

class Car {
public:
Car(int a, int b) {
//some code
}
SetColor(int clr) {
//some code
}
}

//code on mainwindow.cpp
Car *Fiat;

void MainWindow::Method1(int start,int end) {
Fiat = new Car(start,end);
}

void MainWindow::Method2(int color) {
Fiat->SetColor(color);
}

ChrisW67
29th June 2015, 22:33
Yes, but you you now have to manage the allocated object and deallocate the memory ( delete or use a smart pointer) when it is no longer needed.

BTW. Should your Car* be a member variable of the MainWindow class?

jefftee
29th June 2015, 22:45
If all you want to do is make the class visible, but not instantiate it, then just forward declare it as below:



class Car;


If any other code needs to know more than Car is a class, then you should include the header file for your Car class, etc.

arcull
30th June 2015, 06:58
Yes, but you you now have to manage the allocated object and deallocate the memory ( delete or use a smart pointer) when it is no longer needed.

BTW. Should your Car* be a member variable of the MainWindow class?

Ok thanks. Well yes, pointer *Fiat should be a member variable of MainWindow class in my case, I would not like it to be a local variable of a single method, but belonging to the let's say MainWindow class. I know there are other methods for gaining same result, passing by refernce, etc..This example is made up, but I just wanted to know how to do it. Thanks again.

Added after 5 minutes:


If all you want to do is make the class visible, but not instantiate it, then just forward declare it as below:



class Car;

If any other code needs to know more than Car is a class, then you should include the header file for your Car class, etc.

Thanks jefftee, but I'm not sure this is right. Doing
class Car; will create and instance of Car by calling the default constructor with no parameters, just like
class Car();

jefftee
30th June 2015, 07:37
Thanks jefftee, but I'm not sure this is right. Doing
class Car; will create and instance of Car by calling the default constructor with no parameters, just like
class Car();
Actually, it's a forward declaration and does not instantiate the class. Google it or read this (https://en.wikipedia.org/wiki/Forward_declaration) for more info.

arcull
30th June 2015, 12:41
Actually, it's a forward declaration and does not instantiate the class. Google it or read this (https://en.wikipedia.org/wiki/Forward_declaration) for more info. I'm not sure about this. The constructor is called this way. Try the sample below and check output:

car.h

#ifndef CAR_H
#define CAR_H

#include <iostream>

class Car
{
public:
Car() {
std::cout<<"default constructor\n";
}

Car(int a,int b) {
std::cout<<"constructor with 2 params\n";
}
};

#endif // CAR_H
car.cpp

#include "car.h"

Car::Car()
{
}

main.cpp

#include <QCoreApplication>
#include<iostream>
#include "car.h"


int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout<<"starting...\n";

Car Fiat;
Car Audi;

std::cout<<"ending...\n";

return a.exec();

}

stampede
30th June 2015, 13:07
class Car();
This should result in compilation error.

Your code example does not contain forward declaration. Try this way:

#include <QCoreApplication>
#include<iostream>

class Car; // forward declaration of a class Car
// note that the "car.h" is not even included

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout<<"starting...\n";

std::cout<<"ending...\n";

return a.exec();

}

btw. how can you even compile and link your example ? you have multiple definitions of the Car class default constructor.

anda_skoa
30th June 2015, 15:39
I'm not sure about this.

The comment regarding forward declaration was not relevant for your question on delayed instantiation.

But you used "declare an instance" so some readers got the feeling you were asking about declaration without include :)

Cheers,
_

jefftee
30th June 2015, 17:00
I'm not sure about this. The constructor is called this way. Try the sample below and check output:
Your example doesn't forward declare anything. Doesn't matter though, as anda_skoa pointed out, I misunderstood what you were originally asking.

arcull
30th June 2015, 17:22
class Car();
This should result in compilation error.
I guesss that depends on compiler, in my case it doesn't. But you are right, with the "()" you are making compiler think it is a function which returns a class. I've mixed up the declaration and definition in my Car class and you are right again it does not compile. Here is a corrected example:
car.h

#ifndef CAR_H
#define CAR_H

#include <iostream>

class Car
{
public:
Car();
Car(int a, int b);
};

#endif // CAR_H

car.cpp

#include "car.h"

Car::Car()
{
std::cout<<"default constructor\n";
}

Car::Car(int a, int b){
std::cout<<"constructor with 2 params\n";
}

main.cpp

#include <QCoreApplication>
#include <iostream>
#include <car.h>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

std::cout<<"starting...\n";

Car Fiat;
Car Audi;

std::cout<<"ending...\n";
return a.exec();
}
However what I want was already answered at the beginning, that is, create a pointer and crate instance later. My apologies for misleading question and thanks for your help.

stampede
30th June 2015, 17:59
I guesss that depends on compiler, in my case it doesn't.
I'm just curious, which compiler is it ?

arcull
30th June 2015, 18:25
I'm just curious, which compiler is it ?
MinGW 4.8.2 32bit

stampede
30th June 2015, 19:50
That's one of weirdest things I've seen recently, as it doesn't look anything like a function declaration, as "class" is a reserved keyword in C++.
I tried to reproduce this with g++ 4.8.4, 5.0 and 6.0.0 (experimental build) but they always returned a compilation error. To me it is clearly a syntax error and I really would like to see the whole source code you've used when compiling this as well as warning messages generated with -Wall options. If you don't mind ;)

arcull
30th June 2015, 21:07
That's one of weirdest things I've seen recently, as it doesn't look anything like a function declaration, as "class" is a reserved keyword in C++.
I tried to reproduce this with g++ 4.8.4, 5.0 and 6.0.0 (experimental build) but they always returned a compilation error. To me it is clearly a syntax error and I really would like to see the whole source code you've used when compiling this as well as warning messages generated with -Wall options. If you don't mind ;)Sorry my fault again, I was referring to second line, creation of "Audi" object .


Car Fiat; //default constructor called
Car Audi(); //default constructor not called
class Car(); //compile error

stampede
30th June 2015, 21:24
Ok, that makes sense :)

anda_skoa
1st July 2015, 09:12
Sorry my fault again, I was referring to second line, creation of "Audi" object .


Car Fiat; //default constructor called
Car Audi(); //default constructor not called
class Car(); //compile error


Yeah, that's a tricky one, sometimes used in job interviews :)

The Audi line is a prototype/forward declaration for a function called Audi which returns a Car object.

Cheers,
_

yeye_olive
1st July 2015, 11:00
On a side note, I suppose that the intention that the OP had when writing


Car Audi(); // Actually a function declaration, as explained in this thread

was to perform value initialization, as in


Car Audi{}; // Notice the use of the C++11 syntax, that avoids the "function declaration" problem
pAudi = new Car();

, which is in general not the same as default initialization


Car Audi;
pAudi = new Car;

, although in the case of this particular class Car, both end up doing the same thing (calling Car::Car()).