Here is my code -
#include <iostream>
#include <conio.h>
using namespace std;
class Base
{
public:
int a;
};
//int Base::a = 5;
class Derived : public Base
{
public:
int static a;
};
int main()
{
Derived d;
cout<<d.a;
getch();
return 0;
}
I get a linker error here. But when I do it the other way round -
class Base
{
public:
int static a;
};
int Base::a = 5;
class Derived : public Base
{
public:
int a;
};
I get no error. Can someone please explain what is happening here.
All static members have to be explicitly defined/initialized outside the class.
In the second example you do this correctly (int Base::a=5), but in the first example you don't do this for Derived::a, adding the following line to the first example should solve it:
int Derived::a = 5;
You need to actually define static members. The same way as you do
int Base::a = 5
in the second case you should have done
int Derived::a = 5;
in the first case.
There are two questions here.
The first is why do you get the linker error in the first example?
Well, you get a linker error in the first example because you have not defined/initialized the static member of class B.
The second question is why does the compiler not complain of multiple declarations?
The compiler does not complain of multiple declarations because as far as it is concerned, the two variables are in different scopes and their mangled names will be different anyway. This has got nothing to do with one of the variables being static. In fact, static members are not even inherited. SO, the following code snippet without static variables is also correct:
class B {
public:
int a;
};
class C: public B {
public:
int a;
};
Related
When i compile the code below i don't get any error and on debugging it initializes the class data member a of class
abc to zero. Can someone just tell me how is the compiler differentiating between the two. I dont see it happening in runtime.
//A function friendly to two classes (finding maximum of objects of 2 classes(one data member in class)
#include <iostream>
#include <conio.h>
using namespace std;
class abc; //Forward Declaration
class xyz
{
int x;
public :
void inivalue(float);
friend float max(xyz,abc);
};
class abc
{
int a;
public :
void inivalue(float);
friend float max(xyz,abc);
};
void xyz::inivalue(float y)
{
x=y;
}
void abc::inivalue(float a)
{
a=a;
}
float max(xyz m,abc n)
{
if(m.x > n.a)
return m.x;
else
return n.a;
}
int main()
{
system("cls");
xyz o1;
abc o2;
o1.inivalue(10);
o2.inivalue(20);
cout<<"The maximum of 2 classes is : "<<max(o1,o2)<<endl;
}
That's called "variable shadowing".
When you do that, the local variable a "shadows" the class variable. The compiler will use the local variable, so in the inivalue function of the class abc you're just setting the parameter value to itself.
The a member of the class is unitialized when it is used in the max and the code will result in Undefined Behaviour.
#include <iostream>
using namespace std;
class A{
private:
int x;
public:
A(){
x=0;
}
A(int i)
{
x=i;
}
int Get_x(){
return x;
}
};
class B{
private:
A objA(1);
public:
objA.Get_x();
};
This is my code and it has two classes i.e A and B ..First class runs fine but in class B ..compiler gives the syntax error in the declaration of objB.....But as far as i know it should be correct ...so plz help ....thanks
This initialization is invalid for a data member:
A objA(1);
You need
A objA{1};
or
A objA = A(1);
Besides that, this kind of statement can only happen inside of a function:
objA.Get_x();
The compiler is trying to interpret A objA(1) as a function declaration, which is wrong. You may declare objA as A objA = A(1); (please note that thi is a C++11 feature, you may need to enable it before).
Also, I don't really know what objA.Get_x() should do, but this is also wrong, you can't just access a member outside of a function. Probably, you meant this:
int Get_x() {
return objA.Get_x();
}
Im trying to do a C++ class function that can return other classes values. The code works if class A is defined first but i have more code that i dont want to mangle around. I figured i need somekind of forward declaration for class A.
What kind of forward declaration do i need to get this work? All my code is in one file. Does this problem dissapear if i properly split my classes to multiple files and include them to project or does it make any difference to VC++ compiler?
Semi pseudo code below.
// forward declaration
class A;
// class deifinitions
class B {
private:
int testvalue;
public:
void settestvalue(A &Aobj);
}
void B::settestvalue(A &Aobj) {
testvalue = Aobj.settestvalue();
}
class A {
private:
int test = 10;
public:
int testvalue();
};
int A::testvalue() {
return test;
}
// mainloop
A Aobj;
B Bobj;
Bobj.settestvalue (Aobj);
just put the defination of B's member-function after A's class definition.
Very new to c++ having trouble calling a function from another class.
Class B inherits from Class A, and I want class A to be able to call a function created in class B.
using namespace std;
class B;
class A
{
public:
void CallFunction ()
{
B b;
b.bFunction();
}
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
It all looks fine on screen (no obvious errors) but when I try to compile it i get an error C2079 'b' uses undefined class B.
I've tried making them pointers/ friends but I'm getting the same error.
void CallFunction ()
{ // <----- At this point the compiler knows
// nothing about the members of B.
B b;
b.bFunction();
}
This happens for the same reason that functions in C cannot call each other without at least one of them being declared as a function prototype.
To fix this issue we need to make sure both classes are declared before they are used. We separate the declaration from the definition. This MSDN article explains in more detail about the declarations and definitions.
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{ ... }
};
void A::CallFunction ()
{
B b;
b.bFunction();
}
What you should do, is put CallFunction into *.cpp file, where you include B.h.
After edit, files will look like:
B.h:
#pragma once //or other specific to compiler...
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
B.cpp
#include "B.h"
void A::CallFunction(){
//use B object here...
}
Referencing to your explanation, that you have tried to change B b; into pointer- it would be okay, if you wouldn't use it in that same place. You can use pointer of undefined class(but declared), because ALL pointers have fixed byte size(4), so compiler doesn't have problems with that. But it knows nothing about the object they are pointing to(simply: knows the size/boundary, not the content).
So as long as you are using the knowledge, that all pointers are same size, you can use them anywhere. But if you want to use the object, they are pointing to, the class of this object must be already defined and known by compiler.
And last clarification: objects may differ in size, unlike pointers. Pointer is a number/index, which indicates the place in RAM, where something is stored(for example index: 0xf6a7b1).
class B is only declared but not defined at the beginning, which is what the compiler complains about. The root cause is that in class A's Call Function, you are referencing instance b of type B, which is incomplete and undefined. You can modify source like this without introducing new file(just for sake of simplicity, not recommended in practice):
using namespace std;
class A
{
public:
void CallFunction ();
};
class B: public A
{
public:
virtual void bFunction()
{
//stuff done here
}
};
// postpone definition of CallFunction here
void A::CallFunction ()
{
B b;
b.bFunction();
}
in A you have used a definition of B which is not given until then , that's why the compiler is giving error .
Forward declare class B and swap order of A and B definitions: 1st B and 2nd A. You can not call methods of forward declared B class.
Here's my solution to the issue. Tried to keep it straight and simple.
#include <iostream>
using namespace std;
class Game{
public:
void init(){
cout << "Hi" << endl;
}
}g;
class b : Game{ //class b uses/imports class Game
public:
void h(){
init(); //Use function from class Game
}
}A;
int main()
{
A.h();
return 0;
}
You can also have a look at the curiously recurring template pattern and solve your problem similar to this:
template<typename B_TYPE>
struct A
{
int callFctn()
{
B_TYPE b;
return b.bFctn();
}
};
struct B : A<B>
{
int bFctn()
{
return 5;
}
};
int main()
{
A<B> a;
return a.callFctn();
}
class B {
public:
static int a;
};
class C:B {
};
I want to use a variable through any inherited classes but it has problem when I declare a.
B::B() {
a=1;
};
Do I do it right ?
Thanks for reading and waiting for your comments.
// I miss semicolons which is not the error I'm talking .
// This is an error when I try to delcare
class GameState {
public:
static int a = 1;
//...
};
Error 7 error C2864: 'CGameState::a' : only static const integral data members can be initialized within a class d:\my dropbox\work\#today\gdimario\gdimario\gamestate.h 18
I try to write a simple question which shows the problem I want instead of pasting my whole code.
You can use it directly like you did from both the derived and base class.
Perhaps your error is that you don't have semicolons at the end of your class declarations?
class B {
public:
static int a;
};
class C:B {
};
If you want to call it from an instance of C then you need to use public inheritance: (If nothing is specified private inheritance is assumed)
class C : public B {
};
To initialize a you need to do this (typically at the top of your corresponding .CPP file):
int B::a = 3;
You need to write in a CPP file:
int B::a;
And add the semicolons that Brad suggests. (Did you even compile your code? What did the compiler say?)
i think you ll get linker error.
since you have not defined of the static variable in the .cpp file.
e.g.
//hearer file
class X{
public : static int a ;
}
//impl file
int X::a(0);
....or...
For integral type you can also defined static variables when they are declared like:
class X{
public : static int a = 0;
}