C++ Object Initialization outside main - c++

I have some C++ code that produces an error:
class foo{
public:
int a;
int b;
};
foo test;
test.a=1; //error here
test.b=2;
int main()
{
//some code operating on object test
}
I get this error:
error: expected constructor, destructor, or type conversion before '.' token
What does the error mean and how do I fix it?

It's called a constructor. Include one that takes the wanted values as arguments.
Like
class foo
{
public:
foo(int aa, int bb)
: a(aa), b(bb) // Initializer list, set the member variables
{}
private:
int a, b;
};
foo test(1, 2);
As noted by chris, you can also use aggregate initialization if the fields are public, like in your example:
foo test = { 1, 2 };
This also works in C++11 compatible compilers with the constructor as in my example.

This should be:
class foo
{
public:
int a;
int b;
};
foo test;
int main()
{
test.a=1;
test.b=2;
}
You can not write code outside of a method/function, you can only declare variables/classes/types, etc.

You need a default constructor:
//add this
foo(): a(0), b(0) { };
//maybe a deconstructor, depending on your compiler
~foo() { };

You cannot call the variable initialization outside a function. As mentioned in a comment
test.a=1
test.b=2
is thus invalid. If you really need an initialization, use a constructor like
class foo
{
public:
foo(const int a, const int b);
int a;
int b;
}
Otherwise you could put the initialization e.g. into the main function.

Related

Why is it allowed to have a class that has an incomplete type static member of itself?

I am having a hard time understanding why a class can have an incomplete type static member of itself.
For example in my code below. Why is it allowed to have an incomplete type static member of itself inside class A, but the global static variable of class type B gets an error when it is an incomplete type?
class B {
public:
B(int a) {
}
};
static B test2; //error
class A {
public:
static A test; //accepted
A(int d) {
}
};
Can someone explain to me perhaps what is going behind the scenes that gives the global static variable an error and why the static variable inside class A is accepted?
Conflating a couple of dissimilar issues here
static B test2; //error
fails because B's constructor requires arguments that haven't been provided and is private so it can't be accessed outside the class. Correct those and B is good to go.
class B {
public: // added for outside access to constructor
B(int a) {
printf("%d\n", a);
}
};
static B test2{1}; // added arguments
As for A, a static member is not part of a class instance, so the compiler doesn't need it to be complete. It doesn't take up any space, and at this point it's not being used for anything. It's just a declaration. You can declare all sorts of stuff without the compiler getting upset (so long as the declaration's syntax is good). You run into trouble when you try to use something without a definition.
Example:
void testfunc(const A &)
{
}
int main(){
testfunc(A::test);
}
fails at the linker because A::test was never defined. If you try to correct that with
class A {
public:
static A test{1}; // let's try to define it inline!
int a;
int b;
int c;
A(int d, int e) : a(d), b(e), c(15) {
}
A(int d) :A(d, 10) {
printf("%d %d %d", a, b, c);
}
};
now the compiler cares enough to report that the class is incomplete. We'll have to move the definition outside the class where it is complete
class A {
public:
static A test; //declared
int a;
int b;
int c;
A(int d, int e) : a(d), b(e), c(15) {
}
A(int d) :A(d, 10) {
printf("%d %d %d", a, b, c);
}
};
A A::test{1}; // defined
Now
void testfunc(const A &)
{
}
int main(){
testfunc(A::test);
}
will compile and link.
Documentation on the care and feeding of static members.

Why no other constructor is being allowed?

I am learning about initializer list and learnt that const members must be initialized using it, because you cannot initialize it using default constructor or parameterised constructor.
class Foo
{
private:
const int y;
public:
Foo(int yy) :y(yy){}
int getY();
};
Now suppose if I have another member int x; not a const,Why can't I initialize it using default constructor, What is the idea behind this restriction?
The code that gives error:
class Foo
{
private:
const int y;
int x;
public:
Foo(int yy) :y(yy){}
Foo()
{
x = 100;
}
int getY();
};
I am learning about initializer list and learnt that const members must be initialized using it, because you cannot initialize it using default constructor or parameterised constructor.
Const members can be initialized in the member initializer list of both a default constructor and any parametrised constructor. (A default constructor is a constructor that can be invoked without parameters.)
Now suppose if I have another member int x; not a const,Why can't I initialize it using default constructor, What is the idea behind this restriction?
You can initialize any number of members (there is probably some implementation defined limit, but it's not relevant to this question) in the default constructor. There is no such restriction that you describe.
Demo, class with two members, both initialized in the default constructor:
struct Foo {
const int y;
int x;
Foo(): y(1), x(100){}
};
Edit for the mcve.
The code that gives error:
class Foo
{
private:
const int y;
int x;
public:
Foo(int yy) :y(yy){}
Foo()
{
x = 100;
}
int getY();
};
All constructors must initialize const members. Your parametrised constructor does initialize y, but the default constructor doesn't. That is why it doesn't work. See my demo above for a working example.
PS. Your parametrised constructor doesn't initialize x, but that is OK: x isn't const, so you can assign a value to it later.
In my code if I have a parameterised constructor like Foo(int xx) { x = xx;}
It will not give any error
This program:
struct Foo {
const int y;
int x;
Foo(int xx) { x = xx;}
};
Is ill formed in standard C++. If your compiler accepts it without a warning, then it isn't standard compliant.
Unclear what you're trying to accomplish.
Following code simply compiles
class Foo
{
private:
int _nonConst;
const int _const;
public:
Foo() : _const(10), _nonConst(11)
{
}
Foo(int x) : _const(x), _nonConst(x)
{
}
};
I am not sure I understood the question properly. To summarize what you can and can't do:
// .h
class MyClass
{
private:
int x;
const int y;
public:
MyClass();
MyClass(int initValue);
};
// .cpp
// The following is legal
MyClass::MyClass()
: x(0), y(0)
{}
// Alternatively, the following is legal too.
MyClass::MyClass()
: y(0)
{
x = 0;
}
// This is not legal: y cannot be initialized that way as it is const.
// No problem for x though.
MyClass::MyClass()
{
x = 0;
y = 0; // You cannot do that
}
// The following is legal
MyClass::MyClass(int initValue)
: x(initValue), y(initValue)
{}
// Alternatively, the following is legal too.
MyClass::MyClass(int initValue)
: y(initValue)
{
x = initValue;
}
// This is not legal: y cannot be initialized that way as it is const.
// No problem for x though.
MyClass::MyClass(int initValue)
{
x = initValue;
y = initValue; // You cannot do that
}
Of course, you can only have one CTor per declared signature. The examples above are 3 alternatives - 2 legal and 1 illegal - per declared signature.

C++ How to instantiate an object with parameterised constructor?

I have some understanding problems in C++ with parameterised constructors.
If I have a class with one constructor which have two function parameters, how can i instantiate it in an other class header file?
For example:
public:
MyFunction myfunction(param1, param2); //makes an error
How can i declare an object like this?
You need to write MyFunction myfunction; in the class declaration.
Then in the member initialiser list of the constructor to the class of which myfunction is a member, write
/*Your constructor here*/ : myfunction(param1, param2)
{
/*the constructor body*/
}
The bit after the colon is the member initialiser list. param1 and param2 are obviously arguments to that constructor.
You have several ways:
struct P
{
P(int a, int b) :a(a), b(b){}
int a;
int b;
};
struct S
{
S() : p1(4, 2) {} // initializer list
P p1;
P p2{4, 2}; // since c++11
P p3 = P(4, 2); // since c++11
};
An option is having a predeclaration and a pointer to the class.
classA.h
class A
{
public:
A(a,b);
};
classB.h
class A;
class B{
public:
A* foo;
B();
~B();
}
classB.cpp
#include classA.h
#include classB.h
B()
{
foo=new A(a,b);
}
~B()
{
delete(foo);
}
As far as I understand, the problem is that MyFunction has only one constructor that only accepts two arguments.
You can use a pointer to that object and then initialize it in the constructor:
#include <memory>
class Something {
public:
std::shared_ptr<MyFunction> data;
Something(int par1, int par2) {
data = std::shared_ptr<MyFunction>(new MyFunction(par1, par2)); // here you go!
}
~Something() {
//delete data; no need to do this now
}
};
Edit: added a smart pointer to follow rule of three.

C++ instantiate class inside a class with ctor parameters

I have a problem with instantiating a class as a member of another class.
Here is my code:
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i){
printf("myClassA ctor got %d\r\n",i);
threeMyI = i;
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC(){
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB(29); //<== Not working why??
};
I have a class myClassC which I want to have two members, one of type myClassA and one myClassB. This works well for myClassA. But as soon as I try to create an instance of myClassB, which has an ctor parameter, it fails with the following compiler error:
..\src\main.cpp:34:21: error: expected identifier before numeric constant
myClassB instanceB(29); //<== Not working why??
..\src\main.cpp:34:21: error: expected ',' or '...' before numeric constant
In my main function this type of declaration works well:
int main(void){
printf("class test\r\n");
myClassC instanceC1;
myClassA instanceA1;
myClassB instanceB1(25);
return 0;
}
But I have no idea what makes the big difference when instantiating a class with ctor parameters. Hope somebody can give me an hint what I'm doing wrong.
You can only declare member variables, you cannot instantiate them.
To invoke the constructor of a member-variable you can use the memberwise initialization paradigm in your own constructors:
struct A { // same as class A but public by default
int m_a;
A(int a) : m_a(a) {}
};
struct B {
A m_a;
int m_b;
B(int a, int b) : m_a(a), m_b(b) {}
};
Or using your code:
#include <cstdio>
class myClassA{
public:
myClassA(){
printf("myClassTwo ctor");
}
void doSomething(){ printf("myClassA did something\r\n");}
};
class myClassB{
public:
myClassB(int i) : threeMyI(i) {
printf("myClassA ctor got %d\r\n",i);
}
private:
int threeMyI;
};
class myClassC{
public:
myClassC() : instanceA(), instanceB(20) {
printf("C ctor without params\r\n");
}
myClassA instanceA;
myClassB instanceB;
};
int main()
{
myClassA a;
myClassB b(10);
myClassC c;
}
Live demo
From what I have understand, it seems that you want to use a default instantiation for your private attribute instanceB. In that case, what you are proposing is not legal, default input parameters should be set as followed
myClassC() : instanceB(29) { // mind the ":" character
printf("C ctor without params\r\n");
}
This will have the effect to call the constructor of myClassB to instantiate your private attribute instanceB with relevant default parameter.

Passing to a function argument a reference member variable

Is it possible to pass to a function that has a reference argument a variable member of a class?
Let's say
class Foo
{
int A;
int B;
}
void foo(int& a)
{
a++;
}
void main()
{
Foo f;
foo(f.A);
}
Is this possible?
Yes, this is possible, and it works exactly how you expected it to.
But note that in your existing code, A and B are private (by default). That means nothing outside the class can access them, for any reason (which includes using them as references).
Declare them as them public:
class Foo
{
public:
int A;
int B;
};
or change Foo to a struct:
struct Foo
{
int A;
int B;
};