how to call another class's member function? - c++

I have two class, class A, Class B, in class B has a static function like below:
class A {
public:
void method(){ B::method(); }
};
class B {
public:
static int method() {
cout << "method of b" << endl;
}
};
int main()
{
class A a;
a.method();
}
this code build error, because in class A, B is not be declared, but I want class A be defined earlier than class B, how should i do? I was thought it may need forward declaration, but it seems not this reason...

Take a look at the modified code. Inline comments explain the changes:
class A {
public:
// only declare the method
void method();
// Do NOT define it here:
// { B::method(); }
};
class B {
public:
static int method() {
std::cout << "method of b" << std::endl;
return 0;
}
};
// and now, as B implementation is visible, you can use it.
// To do this, you can define the previously declared method:
void A::method() { B::method(); }
int main()
{
class A a;
a.method();
}
Hint: Please never use using namespace std

Related

Scope resolution in c++

I have a program:
#include <iostream>
using namespace std;
class A {
public:
virtual void Output() {
cout << "A";
}
};
class B :public A {
public:
A::Output();
void Output() {
cout << " B ";
}
};
int main() {
A* a = new B;
a->Output();
return 0;
}
I don't understand why the line "A::outPut()" has an error. Please help me with this question.
When used in a method of a subclass of A, the A::Output() is an expression calling the Output method from the A class. As any other executable expression, it can only be use inside a method and not in the class body. Because the class body should only contain declarations (and definitions). For example, you cannot call functions at a class body level.

Two Classes Befriending Each Other

I'm trying to make two classes friend with each other, but I keep getting a "Use of Undefined type A" error message.
Here is my code:
I've tried to add class A; as shown on top but still the same.
#include <iostream>
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA)
{
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl;// Since B is friend of A, it can access private members of A
}
friend class A;
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB){
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl;
}
friend class B; // Friend Class
};
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
system("pause");
return 0;
}
I'm trying to make class A access class B and vice versa via the friendship.
You can't access myFriendA.aVariable because the compiler doesn't know it exists. All it knows is that a class A exists (because of the forward declaration on the second line), but it hasn't been fully defined so it has no idea what its members/methods are.
If you wanted to make this work, showA() would have to be declared outside of the class scope.
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA);
friend class A;
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB){
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl;
}
friend class B; // Friend Class
};
// Define showA() here
void B::showA(A &myFriendA)
{
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl;
}
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
system("pause");
return 0;
}
As #user888379 pointed out, moving the implementation of showA and showB methods after both classes have been completely declared will solve your problem. Following is working code:
#include <iostream>
class A;
class B
{
private:
int bVariable;
public:
B() :bVariable(9){}
void showA(A &myFriendA);
friend class A; // Friend Class
};
class A
{
private:
int aVariable;
public:
A() :aVariable(7){}
void showB(B &myFriendB);
friend class B; // Friend Class
};
void B::showA(A &myFriendA) {
std::cout << "A.aVariable: " << myFriendA.aVariable << std::endl; // Since B is friend of A, it can access private members of A
}
void A::showB(B &myFriendB) {
std::cout << "B.bVariable: " << myFriendB.bVariable << std::endl; // Since A is friend of B, it can access private members of B
}
int main() {
A a;
B b;
b.showA(a);
a.showB(b);
return 0;
}
Read this answer for more detailed analysis.

Shared variable among classes c++

I have multiple classes that need to share a single instance of another class. Publicly it should be unknown that this class exists. Is it appropriate to do something like the following? (Was tested as written)
#include <iostream>
class hideme
{
private:
int a;
public:
void set(int b) { a = b; }
void add(int b) { a += b; }
int get() { return a; }
hideme() : a(0) { }
};
class HiddenWrapper
{
protected:
static hideme A;
};
hideme HiddenWrapper::A;
class addOne : public HiddenWrapper
{
public:
void add() { A.add(1); }
int get() { return A.get(); }
};
class addTwo : public HiddenWrapper
{
public:
void add() { A.add(2); }
int get() { return A.get(); }
};
int main()
{
addOne a;
addTwo b;
std::cout << "Initialized: " << a.get() << std::endl;
a.add();
std::cout << "Added one: " << a.get() << std::endl;
b.add();
std::cout << "Added two: " << b.get() << std::endl;
return 0;
}
For what it's worth, hideme is part of a library I'm attempting to design a facade around, and the other classes have members from the library that interact with the static hideme.
Additionally, if the header file written for HiddenWrapper has no corresponding source file, is that the best place to define its static member? With an include guard.
Is there any other method to solve this problem? As far as I could imagine (not terribly far) I could only solve it otherwise with friendship, which I am wary of.
You can prevent access to a class by not making it accessible outside the translation unit that uses it.
// public_header.h
class A {
void bar();
};
class B {
void foo();
}
// private_implementation.cpp
#include "public_header.h"
namespace {
class hidden { void baz() {} };
hidden h;
}
void A::bar() {
h.baz();
}
void B::foo() {
h.baz();
}
This class will be usable only by A::bar and B::foo. The type hidden and the variable h still technically have external linkage, but no other translation unit can say their names.
Sometimes it is a better idea to inject shared ressources (by reference or pointer) through the constructor (also known as composition instead of inheritance). This way gives you the ability to share or not (e.g. to have a thread-safe variant of your code which is not). See http://de.wikipedia.org/wiki/Inversion_of_Control principle for more info.
This implements a singleton around some other class and hides it from
users:
class hideme {};
// fwd declarations
class x;
// library internal
class S
{
S() = delete;
S(S const&) = delete;
void operator=(S const&) = delete;
private:
static hideme& getInstance()
{
static hideme instance;
return instance;
}
friend x;
};
// library classes
class x {
hideme& s;
public:
x() : s(S::getInstance()) {}
};
int main()
{
x x;
return 0;
}
This does not handle cases where you actually want the hideme
instance to be destroyed when no other object is using it anymore. For
that you need to get a little bit more inventive using reference
counting.
I also should say that I think this is a bad idea. Singletons almost
always are.
Generally, the best approach, if you have a variable in the main part, and want to share it with all classes.
For example, if class X makes a change on this var, the change happened to the var in the main as well: you can use EXTEND
************************ The main *********************
#include <iostream>
using namespace std;
#include "Game.hpp"
//0: not specified yet; 1:singlemode; 2:multiplayerMode
int playingMode = 0;
int main()
{
Game game;
game.Run();
std::cout<< playingMode << std::endl;
return 0;
}
*********************** Class X *****************
#include <iostream>
using namespace std;
extern int playingMode;
....
....
if(m_isSinglePressed)
{
playingMode = 1;
...
}
else if(m_isMultiPressed)
{
playingMode = 2;
...
}

c++ forward declaration

#include <iostream>
#include <cstring>
using namespace std;
class Obj;
class Test {
friend class Obj;
public:
Test()
{
}
~Test()
{
}
void foo()
{
//print();
//Obj::print();
//Obj x;
//x.print();
}
};
class Obj {
public:
void print()
{
cout << "print here" << endl;
}
};
int main()
{
Test test;
test.foo();
return 0;
}
Quick question,how can I call print the correct way in Test::foo() ?
You need to define the member function after the definition of Obj:
class Test {
public:
void foo();
};
class Obj {
public:
void print() { }
};
void Test::foo() {
Obj o;
o.print();
}
As mentioned by james you should define the member function after the definition of Obj. Also you are calling Obj::print, but print is not a static member function so you must call it on an instance of Obj not Obj itself.
If you really do want print to be a static member, declare it so.
class Obj {
public:
static void print(){ blah }
}
Also you do not need to make Obj a friend in order to access its public methods.
Also can OP please define "correct way", I was assuming you wanted it to be a static member function, james' answer is correct if you want one instance of Obj per instance of Test.
UPDATED
OP, as per your comment you must have the declaration of Obj along with print BEFORE using it within Test. This can be achieved in many ways:
move the entire class Obj defintion (and declaration) before Test
declare Obj's methods with its class definition and define them later.
declare Test like you have and Define Test as per James' post (after Obj).
The following works fine:
#include <iostream>
#include <cstring>
using namespace std;
class Obj {
public:
static void print()
{
cout << "print here" << endl;
}
};
class Test {
public:
Test()
{
}
~Test()
{
}
void foo()
{
Obj::print();
}
};
int main()
{
Test test;
test.foo();
return 0;
}
However it is always nicer (in my opinion) to separate declaration from definition for all but the most trivial of cases.

Nested Class member function can't access function of enclosing class. Why?

Please see the example code below:
class A
{
private:
class B
{
public:
foobar();
};
public:
foo();
bar();
};
Within class A & B implementation:
A::foo()
{
//do something
}
A::bar()
{
//some code
foo();
//more code
}
A::B::foobar()
{
//some code
foo(); //<<compiler doesn't like this
}
The compiler flags the call to foo() within the method foobar(). Earlier, I had foo() as private member function of class A but changed to public assuming that B's function can't see it. Of course, it didn't help. I am trying to re-use the functionality provided by A's method. Why doesn't the compiler allow this function call? As I see it, they are part of same enclosing class (A). I thought the accessibility issue for nested class meebers for enclosing class in C++ standards was resolved.
How can I achieve what I am trying to do without re-writing the same method (foo()) for B, which keeping B nested within A?
I am using VC++ compiler ver-9 (Visual Studio 2008). Thank you for your help.
foo() is a non-static member function of A and you are trying to call it without an instance.
The nested class B is a seperate class that only has some access privileges and doesn't have any special knowledge about existing instances of A.
If B needs access to an A you have to give it a reference to it, e.g.:
class A {
class B {
A& parent_;
public:
B(A& parent) : parent_(parent) {}
void foobar() { parent_.foo(); }
};
B b_;
public:
A() : b_(*this) {}
};
This is an automagic, albeit possibly nonportable trick (worked on VC++ since 6.0 though). Class B has to be a member of class A for this to work.
#ifndef OUTERCLASS
#define OUTERCLASS(className, memberName) \
reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
#endif
class A
{
private:
class B
{
public:
void foobar() {
A* pA = OUTERCLASS(A, m_classB);
pA->foo();
}
} m_classB;
public:
foo();
bar();
};
Basically what Georg Fritzsche said
#include <iostream>
#include <cstring>
using namespace std;
class A
{
private:
class B
{
A& parent_;
public:
//B(); //uncommenting gives error
~B();
B(A& parent) : parent_(parent) {}
void foobar()
{
parent_.foo();
cout << "A::B::foo()" <<endl;
}
const std::string& foobarstring(const std::string& test) const
{
parent_.foostring(test); cout << "A::B::foostring()" <<endl;
}
};
public:
void foo();
void bar();
const std::string& foostring(const std::string& test) const;
A();
~A(){};
B b_;
};
//A::B::B() {}; //uncommenting gives error
A::B::~B(){};
A::A():b_(*this) {}
void A::foo()
{
cout << "A::foo()" <<endl;
}
const std::string& A::foostring(const std::string& test) const
{
cout << test <<endl;
return test;
}
void A::bar()
{
//some code
cout << "A::bar()" <<endl;
foo();
//more code
}
int main(int argc, char* argv[])
{
A a;
a.b_.foobar();
a.b_.foobarstring("hello");
return 0;
}
If you uncomment the default B constructor you would get an error
If you want to reuse functionality from A then you should inherit from A not nest B inside it.
Combining Igor Zevaka's and enthusiasticgeek's answers. Also, using reinterpret_cast for calculating offset (If you create class member variable using new keyword):
#include <iostream>
#include <cstring>
using namespace std;
template < typename T, typename U > constexpr size_t offsetOf(U T:: *member)
{
return (char*) &((T*) nullptr->*member) - (char*) nullptr;
}
class A
{
private:
class B
{
public:
B(string message);
~B();
void foobar()
{
A *pA = reinterpret_cast<A*> (reinterpret_cast< unsigned char*> (this) - offsetOf(&A::b_));
pA->foo();
pA->bar();
std::cout << "DONE!";
}
};
public:
void foo();
void bar();
A();
~A() {};
B* b_ = new B("Hello World!");
};
A::A()
{
cout << "A constructor\n";
};
A::B::B(string message) {
cout << "B constructor\n";
cout << "Message = " << message << "\n";
};
A::B::~B() {};
void A::foo()
{
cout << "A::foo()" << endl;
}
void A::bar()
{
cout << "A::bar()" << endl;
foo();
}
int main(int argc, char *argv[])
{
A* a = new A();
a->b_->foobar();
return 0;
}
Output:
B constructor
Message = Hello World!
A constructor
A::foo()
A::bar()
A::foo()
DONE!
References:
https://stackoverflow.com/a/10607424/9524565
https://stackoverflow.com/a/3058382/9524565
https://stackoverflow.com/a/20141143/9524565