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.
Related
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
I not sure how to ask this but basically i pass a base class as an parameter and if the argument is a derived class from the base class i want to be able to access properties only in the derived class
class A{
public:
bool isB = false;
int x = 69;
}
class B : public A{
public:
bool isB = true;
int y = 420;
}
void Print(A c){
if (c.isB)
cout << c.y << endl; //this will error as the class A has no y even though i will pass class B as an argument
else
cout << c.x << endl;
}
A a;
B b;
Print(a);
Print(b);
My recommendation is that you use polymorphism by creating a virtual "print" function that your global Print function calls:
class A
{
int x = 69;
public:
virtual ~A() = default; // Needed for polymorphic classes
virtual void print(std::ostream& out) const
{
out << x;
}
};
class B : public A
{
int y = 420;
public:
void print(std::ostream& out) const override
{
out << y;
}
};
void Print(A const& o)
{
o.print(std::cout);
std::cout << std::endl;
}
int main()
{
A a;
B b;
Print(a);
Print(b);
}
You need to define a virtual function "bool amIaB()" in both base and derived class that returns "isB".
Yes I know that private modifier created in order to prohibit access to class data
but isn't friend intended to allow special access to it?
Compiler:
main.cpp: In member function 'void C::blah(B&)':
main.cpp:48:26: error: 'int B::a' is private within this context
std::cout << obj.a << std::endl;
Everything below is implemented the way as it is in many tutorials.
May be it's just a silly mistake I made and blind to spot.
class C;
class B {
private:
int a = 2;
public:
friend void blah(B& obj);
};
class C {
public:
void blah(B& obj) {
std::cout << obj.a << std::endl; //*
}
};
*Member B::a is inaccessible
You're declaring a non-member function named blah, but not C::blah as friend.
You could change your code to the following, and note the order of the declaration and definition.
class B;
class C {
public:
void blah(B& obj);
};
class B {
private:
int a = 2;
public:
friend void C::blah(B& obj);
};
void C::blah(B& obj) {
std::cout << obj.a << std::endl;
}
LIVE
If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.
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