Sorry if this has been asked before; I found similarly titled questions, but none of them focused on the same aspects I'm having trouble with.
There's a class A, and a class B that should only be accessible from A. I think nesting B inside A will achieve that, but I'm struggling with the logistics.
A has a B as a member. As such, not defining B prior to declaring A's members causes incomplete type errors. I thought I'd get around this by declaring A, defining A::B, then defining A, but that just throws the same errors plus incomplete type 'A' in nested name specifier.
class A;
class A::B
{
...
};
class A
{
private:
class B;
B b;
...
};
The only functional examples I can find would put B's member declaration directly inside A's, which I'd really like to avoid doing: B's header information is several times longer and much denser than A's. Splitting the two up into separate files would be best, but actually nesting them inline is incredibly unwieldy.
Fallback options at this point include making A's B a pointer (no real reason why not, but is this really something that can't be done?) and leaving them as independent classes. But surely this can't be that hard?
What do I need to declare to link these properly and in what order?
I am not particularly knowledgeable about the depths of C++ so please explain like I'm five and refrain from shaming me into the ground for not knowing everything.
Since b is a non-reference non static data member of class A, it must be declared to have a complete type.
One way to solve this would be to either make b a reference type(as shown below) or a pointer to a B:
class A
{
private:
class B;
//--vv------------>now b is an lvalue reference to a B object
B& b;
};
class A::B
{
};
Method 2
Other option is to define B inside A with only its member declaration and then define those members outside as shown below:
class A
{
private:
//defined class now
class B
{
void member1();
};
B b; //works now
};
void A::B::member1()
{
}
One particularly non-convoluted way of doing this would be
class B
{
friend class A;
private:
// everything;
};
class A
{
B b;
};
This of course makes all the guts of B accessible to A, bit if B is such A-specific, it should not be a problem.
If this is not desirable, a slightly wore windy path to a solution would be
class PreA
{
protected:
class B { ... };
};
class A : PreA
{
B b;
};
The only functional examples I can find would put B's member
declaration directly inside A's, which I'd really like to avoid doing:
B's header information is several times longer and much denser than
A's. Splitting the two up into separate files would be best, but
actually nesting them inline is incredibly unwieldy.
The premise is interesting until I saw this comment of yours, I assume by you mean "Hide" is "Hide the Code it Self", not the members and method of B?
B is already tailored to the specifics of A and wouldn't be reusable
without modification. That's really why I want to hide it.
And with this line, can I assume that you aren't familiar with the concept of inheritance?
I am not particularly knowledgeable about the depths of C++ so please
explain like I'm five and refrain from shaming me into the ground for
not knowing everything.
You can simply inherit Class A into Class B, then use Class B itself? or the other way around. Just remember that the Base Class [Class A in this Case] has no idea what methods or member the Derived Class has [Class B in this Case].
e.g.All (Derived)Airplanes can (Base)Fly but not everything that can Fly is an airplane.
A Little Introduction to Inheritance can be found here. and if you do decide to go through this route, please Read up on a lot of materials about it. It's a Deep hole.
class A
{
public:
A()
{
x=0;
y=0;
std::cout << "A's Default Constructor Used " << std::endl;
}
virtual ~A(){std::cout<<"A's Destructor called" << std::endl;};
int x;
int y;
};
class B : public A
{
public:
B(){}
B(int nX, int nY){x=nX,y=nY;}
~B(){std::cout<<"B's Destructor Called"<<std::endl;}
public:
void SomeMethod(int nX){x+=nX;}
};
int main() {
B b;
std::cout << b.x << " " << b.y << std::endl;
b.SomeMethod(10);
std::cout << b.x << " " << b.y << std::endl;
}
NOTE: On A's destructor [virtual ~A(){std::cout<<"A's Destructor called" << std::endl;};] the keyword virtual is not needed unless you are deleting / destroying Class B from a Pointer to an Object of Class A, and Absolutely necessary if you are, Like Below.
B* b = new B;
std::cout << b->x << " " << b->y << std::endl;
b->SomeMethod(10);
std::cout << b->x << " " << b->y << std::endl;
A* a = b;
delete a;
Without the virtual keyword, only A's Destructor would be called and not B's.
Unless inheritance is out of the question then Nesting(Which I personally don't recommend it's a big pain on maintenance) ,creating a pointer of Class B inside A.
Or simply create Class B inside Class A like below.
class B
{
public:
B()
{
z = 0;
std::cout<<"B Default Constructor Used"<<std::endl;
}
B(int nZ)
{
z = nZ;
std::cout<<"B Constructed"<<std::endl;
}
~B(){}
public:
void SomeMethod(int& nX,int nY){nX += ( nY + z );}
int z;
};
class A
{
public:
A()
{
x=0;
y=0;
std::cout << "A Default constructor used" << std::endl;
}
A(int nX,int nY,int nZ)
{
x = nX;
y = nY;
b.z = nZ;
std::cout << "A's Constructed" << std::endl;
}
~A(){};
B b;
int x;
int y;
};
int main() {
A a;
a.b.SomeMethod(a.x,10);
std::cout << a.x << std::endl << std::endl;
// Ore something like this;
A a2 = A(1,2,3);
a2.b.SomeMethod(a2.x,20);
std::cout << a2.x << std::endl;
}
Just remember to create a Default Constructor for Class B since it would be called during the creation of Class B. Take note that I am speaking from my personal Experience and Knowledge, and by no means is it gospel, specially when I am self taught, and Using conventions that I am using in my own projects.
Declaring a Class static is one way to prevent Class B's Creation as Well but able to use it's functions . But I rarely find the need to do this in productions. I've mainly used this in debugging things. Since I've only seen it used in C#, and I've never tried it using it in production since I don't know what kind of behavior it could produce.
#include <iostream>
static struct B
{
protected:
B(){};
public:
static void PrintSomething(int x)
{
std::cout <<"Printing Something " << x <<std::endl;
}
static void MultiplyBy2(int* x)
{
int Two = 2;
*x = *x * Two;
}
};
class A
{
public:
A(int nX,int nY):X(nX),Y(nY){}
public:
int GetX()const{return X;}
int GetY()const{return Y;}
int* PointerToX() {return &X;}
private:
int X;
int Y;
};
int main()
{
A a(1,2);
B::PrintSomething(a.GetX());
B::MultiplyBy2(a.PointerToX());
B::PrintSomething(a.GetX());
B::MultiplyBy2(a.PointerToX());
B::PrintSomething(a.GetX());
return 0;
}
Related
I have a class B with a pointer attribute of class A with a method that assigns the pointer attribute to the variable of the other class A. Yet this variable is private, assigning the variable therefore create an error. How can I solve this issue?
#include<iostream>
using namespace std;
class A {
private :
int x;
public:
A(int);
~A();
};
class B {
private :
A * pA;
int y;
public:
B(int, int);
~B();
void imprimer();
};
void B::imprimer() {
cout << "B::imprimer: " << pA->x << " " << y << endl;
}
main()
{
B to(1, 2);
to.imprimer(); //instruction (1)
}
Gives the following result :
$ g++ td4Exercice1_2.cpp -o td4Exercice1_2
td4Exercice1_2.cpp: In member function ‘void B::imprimer()’:
td4Exercice1_2.cpp:7:6: error: ‘int A::x’ is private
int x;
^
td4Exercice1_2.cpp:24:33: error: within this context
cout << "B::imprimer: " << pA->x << " " << y << endl;
What you are missing are the class get() and set(int) methods for class A
OR
You have not declared Class B to be a friend of Class A.
A's x is a private variable within Class A. Only Class A can modify its variables, unless you do a few things.
You declare Class B to be a friend of Class A.
class B; // you must 'declare Class B before Class A for this to work
class A {
friend class B;
private :
int x;
public:
A(int);
~A();
};
This would allow class B full access to anything in Class A. BUT this is a POOR design.
There complex ways to do this as shown in "C++ Primer", S. Lippman that allow the "<<" operators to friend the class for output. QED.
The least intrusive way to do this is to create a new method in class A.
class A {
private :
int x;
public:
A(int);
~A();
int getX( void) { return( x ) };
};
void B::imprimer() {
cout << "B::imprimer: " << pA->getX() << " " << y << endl;
}
now you can get the value of A::x without being able to change it.
This does lead to some greater design problems in that you now have the last value of A::x, though possible not the current value of A::x. x could have been modified before you begin to use the value you have for x.
Further study of using 'friend' with "<<" ">>" operators will show you a better way depending on what the big picture is for your program.
I have a simple question. How would you go about passing an instance of a class to a constructor of another class in c++? I have experience in C, however I am struggling with the syntax of c++.
For example say I have Class A and want to pass and Instance of it to Class B.
A.h
class A {
A();
virtual ~A();
public:
B *newb;
}
A.cpp
A::A() {
newb = new B(this);
}
b.h
class B {
B(A *instanceA);
virtual ~B();
}
Could someone please provide me with a simple example? It would be much appreciated.
EDIT: I tried this concept with my current code, but kept getting errors. Sorry I wanted to make sure that I used the right principle. This is a snippet of the code that I am currently working on.
//SentencSelection.h
class SentenceSelection
{
public:
SentenceSelection(TestBenchGui *test);
virtual ~SentenceSelection();
//do stuff
};
//SentencSelection.cpp
#include <iostream>
#include "SentenceSelection.h"
using namespace std;
SentenceSelection::SentenceSelection(TestBenchGui *test)
{
//do stuff
}
SentenceSelection::~SentenceSelection()
{
}
//TestBenchGui.h
#include "SentenceSelection.h"
class TestBenchGui
{
public:
TestBenchGui();
virtual ~TestBenchGui();
private:
SentenceSelection *selection;
};
//TestBenchGui.cpp
#include "TestBenchGui.h"
#include "SentenceSelection.h"
using namespace std;
TestBenchGui::TestBenchGui()
{
selection = new SentenceSelection(this);
}
TestBenchGui::~TestBenchGui()
{
}
When I compile this in eclipse I get the follwing error "expected constructor, destructor, or type conversion before ‘(’ token" for the line - "SentenceSelection::SentenceSelection(TestBenchGui test)" in SentenceSelection.h.
I believe the code you have does pretty much what you are asking, but there are a couple of syntax errors that are probably holding you back from compilation (and thus leading to some confusion). Below is code that I put in a single file (main.cpp) and was able to compile. I added some comments and print statements to highlight the difference between DECLARATIONS and IMPLEMENTATIONS:
#include <iostream>
using std::cout;
using std::endl;
// forward declaration so we can refer to it in A
class B;
// define A's interface
class A {
public:
// member variables
B *newb;
// constructor declaration
A();
// destructor declaration
virtual ~A();
}; // note the semicolon that ends the definition of A as a class
class B {
public:
// B constructor implementation
B(A *instanceA){cout << "I am creating a B with a pointer to an A at " << instanceA << endl;}
// B destructor implementation
virtual ~B(){cout << "Destructor of B" << endl;}
}; // note the semicolon that ends the definition of B as a class
// A constructor implementation
A::A(){
cout << "I am creating an A at " << this << ", allocating a B on the heap..." << endl;
newb = new B(this);
}
// A destructor implementation
A::~A(){
cout << "Destructor of A, deleting my B...." << endl;
delete newb;
}
int main(){
A an_a;
}
Output for my system from running the above program:
I am creating an A at 0x7fff64884ba0, allocating a B on the heap...
I am creating a B with a pointer to an A at 0x7fff64884ba0
Destructor of A, deleting my B....
Destructor of B
Hope this helps.
For example say I have Class A and want to pass and Instance of it to Class B.
If you intend to pass a pointer to the instance, then you have already figured it out. The constructor that you declared takes an A* as an argument:
B(A *instanceA);
#include <iostream>
using namespace std;
class B
{
public:
B(){};
int x;
~B(){};
};
class A
{
public:
A(){}; // default constructor
A(B& b) // constructor taking B
{
y = b.x;
}
~A(){};
int y;
};
int main()
{
B myB;
myB.x = 69;
A myA(myB);
cout << myA.y << endl;
return 0;
}
I answer strictly your question:
If you want to pass a instance on a constructor best practice is pass as a reference:
class CA{
CB &b;
public:
CA( CB &p_b) : b(p_b){};
virtual ~CA();
};
But in your example you have a classes with cross references that is another case
If I declare a base class (or interface class) and specify a default value for one or more of its parameters, do the derived classes have to specify the same defaults and if not, which defaults will manifest in the derived classes?
Addendum: I'm also interested in how this may be handled across different compilers and any input on "recommended" practice in this scenario.
Virtuals may have defaults. The defaults in the base class are not inherited by derived classes.
Which default is used -- ie, the base class' or a derived class' -- is determined by the static type used to make the call to the function. If you call through a base class object, pointer or reference, the default denoted in the base class is used. Conversely, if you call through a derived class object, pointer or reference the defaults denoted in the derived class are used. There is an example below the Standard quotation that demonstrates this.
Some compilers may do something different, but this is what the C++03 and C++11 Standards say:
8.3.6.10:
A virtual function call (10.3) uses
the default arguments in the
declaration of the virtual function
determined
by the static type of the pointer or reference denoting the object. An
overriding function in a derived
class does not acquire default arguments from the function it
overrides. Example:
struct A {
virtual void f(int a = 7);
};
struct B : public A {
void f(int a);
};
void m()
{
B* pb = new B;
A* pa = pb;
pa->f(); //OK, calls pa->B::f(7)
pb->f(); //error: wrong number of arguments for B::f()
}
Here is a sample program to demonstrate what defaults are picked up. I'm using structs here rather than classes simply for brevity -- class and struct are exactly the same in almost every way except default visibility.
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using std::stringstream;
using std::string;
using std::cout;
using std::endl;
struct Base { virtual string Speak(int n = 42); };
struct Der : public Base { string Speak(int n = 84); };
string Base::Speak(int n)
{
stringstream ss;
ss << "Base " << n;
return ss.str();
}
string Der::Speak(int n)
{
stringstream ss;
ss << "Der " << n;
return ss.str();
}
int main()
{
Base b1;
Der d1;
Base *pb1 = &b1, *pb2 = &d1;
Der *pd1 = &d1;
cout << pb1->Speak() << "\n" // Base 42
<< pb2->Speak() << "\n" // Der 42
<< pd1->Speak() << "\n" // Der 84
<< endl;
}
The output of this program (on MSVC10 and GCC 4.4) is:
Base 42
Der 42
Der 84
This was the topic of one of Herb Sutter's early Guru of the Week posts.
The first thing he says on the subject is DON'T DO THAT.
In more detail, yes, you can specify different default parameters. They won't work the same way as the virtual functions. A virtual function is called on the dynamic type of the object, while the default parameter values are based on the static type.
Given
class A {
virtual void foo(int i = 1) { cout << "A::foo" << i << endl; }
};
class B: public A {
virtual void foo(int i = 2) { cout << "B::foo" << i << endl; }
};
void test() {
A a;
B b;
A* ap = &b;
a.foo();
b.foo();
ap->foo();
}
you should get
A::foo1
B::foo2
B::foo1
This is a bad idea, because the default arguments you get will depend on the static type of the object, whereas the virtual function dispatched to will depend on the dynamic type.
That is to say, when you call a function with default arguments, the default arguments are substituted at compile time, regardless of whether the function is virtual or not.
#cppcoder offered the following example in his [closed] question:
struct A {
virtual void display(int i = 5) { std::cout << "Base::" << i << "\n"; }
};
struct B : public A {
virtual void display(int i = 9) override { std::cout << "Derived::" << i << "\n"; }
};
int main()
{
A * a = new B();
a->display();
A* aa = new A();
aa->display();
B* bb = new B();
bb->display();
}
Which produces the following output:
Derived::5
Base::5
Derived::9
With the aid of the explanation above, it is easy to see why. At compile time, the compiler substitutes the default arguments from the member functions of the static types of the pointers, making the main function equivalent to the following:
A * a = new B();
a->display(5);
A* aa = new A();
aa->display(5);
B* bb = new B();
bb->display(9);
As other answers have detailed, its bad idea. However since no one mentions simple and effective solution, here it is: Convert your parameters to struct and then you can have default values to struct members!
So instead of,
//bad idea
virtual method1(int x = 0, int y = 0, int z = 0)
do this,
//good idea
struct Param1 {
int x = 0, y = 0, z = 0;
};
virtual method1(const Param1& p)
As you can see from the other answers this is a complicated subject. Instead of trying to do this or understand what it does (if you have to ask now, the maintainer will have to ask or look it up a year from now).
Instead, create a public non-virtual function in the base class with default parameters. Then it calls a private or protected virtual function that has no default parameters and is overridden in child classes as needed. Then you don't have to worry about the particulars of how it would work and the code is very obvious.
This is one that you can probably figure out reasonably well by testing (i.e., it's a sufficiently mainstream part of the language that most compilers almost certainly get it right and unless you see differences between compilers, their output can be considered pretty well authoritative).
#include <iostream>
struct base {
virtual void x(int a=0) { std::cout << a; }
virtual ~base() {}
};
struct derived1 : base {
void x(int a) { std:: cout << a; }
};
struct derived2 : base {
void x(int a = 1) { std::cout << a; }
};
int main() {
base *b[3];
b[0] = new base;
b[1] = new derived1;
b[2] = new derived2;
for (int i=0; i<3; i++) {
b[i]->x();
delete b[i];
}
derived1 d;
// d.x(); // won't compile.
derived2 d2;
d2.x();
return 0;
}
class A
{
class B
{
int x;
}
public:
void printX() { std::cout << ????; }
}
How can I access the x variable from the A class function? I can't make it static either...
I tried everything but it either tells me I need an object in order to access it or the compiler doesn't find the function.
it either tells me I need an object [...]
Think about that. Because that's exactly what the problem is here.
If you instantiate an A, you don't also get a B. A nested class isn't a member variable of the enclosing class. It's really just another way to change the namespace of a class.
So, you need an instance of B. Perhaps a member of A?
class A
{
class B
{
public:
int x;
} mB;
public:
void printX() { std::cout << mB.x; }
};
You don't ever declare an instance of the class B inside A. You need to do something like this:
class A
{
class B
{
public:
int x;
};
B b;
public:
void printX() { std::cout << b.x; }
};
You don't. You do need an object in order to use the x variable. You could, however make it static. The problem with your example is x is not public. Placing B inside A does not make B part of A, it only changes B's scope.
From this example it kinda looks like you're after inheritance instead. This would give you the effect you're after ( access to all B's methods and variables without making an object. )
Class B
{
protected:
int x;
}
Class A : B
{
void printX() { std::cout << x; }
}
#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
The code above compiles fine in clang 3.0 and g++ 4.5. However the output is junk (--i.e., not three). Since the compiler doesn't seem to mind, how do I get the code to behave ?
Secondly, If there is some way to make the above slice / conversion to work correctly, how bad would it be if I then did the following, provided a good reason to do it exists :
class c : public a { public: uint64_t x; };
Why I am interested in these semantics.
The reason I want to do this is this. I have a two class heirachies, where one heirarchy (the parent) aggregages objects, on the same heirarchy level, from the other(the child). I use a custom container for the aggregation. I want to typedef the container in the parent class (the typedefs have the same name), and declare the container with the same name at each level of the parent.
The class heirarchies are designed to contain less information at lower levels ( the base classes hold the least), therefore slicing makes perfect sense here.
Edit:
There you go, this should clear things up.
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
The child B has more members than the child class A. However, I wan't to present a uniform interface for code that is only interested in the members of class A.
There is no way to do that if you directly set b::x. a::x and b::x are two different members, and the latter hides the former.
You can still access a::x on an object of type b with static_cast<a&>(bee).x = 3, but the fundamental problem is that the values of a::x and b::x on an object of type b are not synchronized.
If you abstract access to both x members with a "property getter/setter", then you can arrange for the setter on the derived class to also update the member of the base class. Or (maybe this is more appropriate?) you can make the member of the base class protected and use it from the derived class directly, slicing as you need just before returning from the getter.
huh ! its a bit complicated no ?
why don't you use :
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
or
virtual void setA( int value ) { b::x = value; }
or
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
There are two ways of constructing a software design; one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
C.A.R.Hoare
According to Jon's answer, Since a::x and b::x are separate variables, furthermore since b::x masks a::x, if you wanted to get the correct semantics you need to provide a copy conversion constructor. The following code does the trick.
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
Maybe try something like this:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};