It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I want to ask where in C++ is the right place to instantiate a instance-variables? I think it should not be in the class declaration, but otherwise I don`t see any disadvantages apart from poor object-oriented design:
class A{ member m; };
I think it should better be like:
class A{ extern member m; };
But I don`t know how to realize it without a pointer like this:
class A{ member* m };
A::A(){ m = new member; }
Is there a "clean solution" to realize this on the stack (without using pointers)?
You can use the constructor initialization list to construct all your member variables as you need.
A::A(const member& memberArg)
: m(memberArg)
{ }
Look at this for more info.
I think you have a misunderstanding of how objects are instantiated. If all you do is declare a class, no member variables are actually instantiated. It isn't until you construct an instance of that class that its member variables exist.
Here's an example to show when a member object gets instantiated:
class ClassA
{
public:
ClassA() { std::cout << "Hello!\n"; }
};
class ClassB
{
public:
ClassA objA;
};
int main()
{
// do some work
ClassB objB; // here, a ClassB object is created, and with it its member ClassA object, so "Hello!" is printed
return 0;
}
As to exactly how you specify what kind of ClassA object to create if its constructor requires arguments, the other answers do a fine job explaining it.
I think it should not be in the class declaration, but otherwise I don`t see any disadvantages apart from poor object-oriented design:
class A{ member m; };
What in your mind makes this poor OO design? This is the preferred mechanism in C++.
I think it should better be like:
class A{ extern member m; };
This isn't valid code. Qualifying member data with a storage class specification such as extern is illegal.
But I don`t know how to realize it without a pointer like this:
class A{ member* m; };
A::A(){ m = new member; }
That will work, but why do that? It looks to me like you are trying to import a Java POV into C++. Everything is allocated, and everything is a reference in Java. In many (most!) cases there is no reason to allocate data members in C++. All it does is add an unneeded indirection and add a place where memory can leak.
You want to use member initializers: they are the only way to initialize class members that have a constructor that requires parameters, and the cleanest way to initialize other class members.
If you have class A and a member m with a constructor:
class A { member m; }
You want
class A { member m; A(); }
A::A()
: m(<constructor params>)
{
}
You would declare your instance variables in your .h file:
A.h
class A {
public:
A();
private:
int value;
double someOtherValue;
}
You can instantiate them in your .cpp file like so:
A.cpp
A::A(): value(5), someOtherValue(10.0)
{
...
}
If the member object is to be totally controlled by the enclosing A object, your first example is the proper way to do it. It does have the downside of requiring a complete definition of member at the point where A is defined.
You could check out the pimpl idiom to reduce coupling, but that still requires the object to be heap-based and not stack-based.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I'm new into learning C++.
And what I've learned is that using global var is not a good practise.
And I don't wanna use static var, since they behave like "global" var as well, if I'm correct.
In the code below I want class B to get access to its "parents" member, is that possible?(see class B constructor)
Or how should I approach this, where I want to access var/members between classes?
Friends, seems not to be the way either.
class A {
public:
int number_I_want = 987;
A() {
B* classB = new B();
}
};
class B {
public:
int nr = 0;
B() {
nr = this->parent->numer_I_want; /// Here I wanna access the "parent" A's member with value 987
cout << nr * nr;
}
};
int main() {
A* classA = new A();
return 0;
}
Class A is The parent class so if the members/fields are not private . you can access them in class B. But the class B must Be the child of class A. You have to extend class b from A. And if you have parametrized constructor of parent class you must initialize classA constructor from class B
In C++, there is no parent\child relation for object. Sometimes it gets confusing with people coming from languages with object memory model (which are either VM-based or interpreters). Parent there is an object owning this one. C++ uses abstract memory model. If a class Bis inherited from other class A, class A is abase class of B. Base class and class members are subobjects of given class, meaning their storage is part of enclosing object's storage. Consecutively base class's members are subobjects too and are accessible as class members with consideration of access level and inheritance level (private, public, protected).
Enclosing object owns included ones and call to its destructor results in their destruction.
If you need actual parent\child relation , you have to implement it and pass a pointer (?) to parent into child's constructor, while it have to be able to register self within given parent.
Some C++ framework emulate object model by using metaprogramming technique, e.g. Qt Framework's QObject may have a parent and list of children.
Using pointer to >>this<< keyword when creating a "child" class worked for me.
class A {
public:
int nr;
A();
};
class B {
public:
B(A* classA) {
std::cout << "Written in class B, value from class A: "<< classA->nr;
};
};
A::A() {
nr = 77;
B* classB = new B(this);
delete classB;
}
int main() {
A* classA = new A();
delete classA;
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have 2 objects in my C++ program, both extending from the same parent class:
class A, and class B, both extending class base.
Is it possible create an object using class A, and then change it later in the program to class B?
Short answer, no. You cannot safely cast from A to B or B to A. You can safely cast to the base class since A IS_A base class and B IS_A base class but A and not a B and vice versa. There is no portable or safe way to do this. Whilst your compiler might let you do it and whilst it might appear to work the result of casting between to unrelated classes in this manner is undefined.
Incidentally, there is no reason why you can't add a cast constructor to allow A to be constructed from B and vice versa. That would be perfectly safe. You would just use the members of A to initialise the members of B and vice versa. Any members that are not common you'd have to deal with, probably be assigning them default values.
The following code works:
#include <iostream>
class Base {};
struct A : public Base {int a;};
struct B : public Base {int b;};
int main()
{
A *a = new A();
a->a = 1;
B *b = reinterpret_cast<B *>(a);
std::cout << b->b << std::endl;
return 0;
}
This is extremely ugly though and won't work properly if A and B don't have the exact same memory layout. This works if you need a and b to be the same object. If you don't mind them being different objects and residing in different places in memory then you can just write a constructor in B that receives an object of type A or a conversion operator.
This sounds like a classic example of the XY Problem and there probably exists a much more elegant solution to your actual problem.
As others have mentioned, no you cannot do this...technically. You can in fact achieve this effect through convert constructors and virtual functions.
If you write a convert constructor from A to B and B to A:
A::A(B convertFrom); // Convert from B to A
B::B(A convertFrom); // Convert from A to B
And you make the essential parts of each class virtual:
class base
{
virutal void baseClassFunction();
};
class A
{
virtual void baseClassFunction()
{
// Do things for A
}
};
Class B
{
virtual void baseClassFunction()
{
// Do things for B
}
}
Then you can simply make a pointer of type base which can hold a reference to either A or B.
Example bringing it all together;
int main()
{
base *ptr = new A();
bool needs_to_be_B;
...
// Program logic
ptr->baseClassFunction();
...
if(needs_to_be_B)
{
base *tmp = new B(*ptr);
delete ptr;
ptr = tmp;
delete tmp;
}
// ptr is now a B
ptr->baseClassFunction();
}
If you are confused look up virtual functions and convert constructors.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Here's the code:
class B
{
A a;
};
class A
{
B b;
};
int main()
{
return 0;
}
Here's the error:
1>c:\mine\visual studio 2010 projects\myproj\compiled equivalent.cpp(7):
error C2079: 'B::a' uses undefined class 'A'
You can't. Two classes cannot contain each other as members. Consider answering the question “What is the size of the type A?” Well A contains a B, so what is the size of B? Well B contains an A, so what is the size of A? Oh dear, we have an infinite loop. How would we possibly store this object in finite memory?
Perhaps a more appropriate structure would be to have one of the classes contain a pointer to the other type. The type that is pointed to can simply be forward declared before the pointer member is declared:
class A; // A is only declared here, so it is an incomplete type
class B
{
A* a; // Here it is okay for A to be an incomplete type
};
class A
{
B b;
};
Now the type B doesn't contain an A, it just contains a pointer to an A. There doesn't even have to be an A object for it to point to, so we've broken the infinite cycle.
Considering you ask for references between the classes, probably you come from Java, C# or similar background where one can only put references to objects inside other objects.
In C++ there is no such restriction: you are allowed to have one object's content completely nested inside another one. But for this to work you must provide the definition of the nested object beforehand. C++ needs this definition in order to compute the size and layout of the outer object. In order to escape from this nesting you need to place not the object itself but a pointer or reference to it inside the outer object.
That being said,
// C#
class A
{
int x;
B b;
}
class B
{
int y;
A a;
}
becomes
// C++
class B; // tell the compiler that B is a class name
class A
{
int x;
B *pb; // the forward declaration above allows you to declare pointer to B here
};
class B
{
int y;
A *pa;
};
if you decide to use the pointer syntax.
What this allows is to have things like:
// C++ again
class C
{
A a;
B b;
A *pa2;
};
which has memory layout in the form of:
C:
a.xa.pb
b.yb.pa
pa2
which is not possible in Java/C#.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to modify template type given at compile time but unable to do it. Let see if you have some idea.
Lets consider we have 2 classes class A and A_test and one template class B.
Will implemented class B as it is having a function b_f() which is internaly creating an object of template class and calling public funcion A_f()/A_test_f() of class A or Class A_test.
from main, will be creating class B obj; obj.b_f();
but I want to creat an object of class A_test not class A.
Let me know if it is possible.
Basicaly I wanted to do object injection. Please let me know if it is possible.
The best solution by far is to try to rename A_test_f() to be the same as A_f().
If that proves impossible, the next thing I'd try is to specialize class B:
template<class AT>
class B {
public: b_f() {
AT m_A;
m_A.A_f();
};
template<>
class B<A_test> {
public: b_f() {
AT m_A;
m_A.A_test_f();
};
If B is too complicated, there are other things to try, but you probably want to rethink what you're doing first. If all else fails, do what I coded above here, but call it B_HELPER instead of B and then b_f() can do: B_HELPER<AT> m_A; m_A.b_f(); That way you don't have to recode all of B.
The common way to inject dependencies into templates at compile-time is through type traits. This allows customizing the templates externally through another struct or class which has specific knowledge of the class. Examples in the standard library include std::char_traits<> and std::iterator_traits<>. Boost also defines some, including boost::type_traits<>.
Traits involve defining a struct for the general case and specializing it for alternate cases when necessary.
// general case: select method named "f".
template<class T> struct b_traits
{
typedef void(T*F)();
static const F f = &T::f;
};
// template type that forwards method selection to "b_traits" struct.
template<class AT>
class B {
public: b_f() {
AT m_A;
(m_A.*(b_traits<AT>::f))();
};
class A_test { ... };
// special case: select method named "A_test_f".
template<> struct b_traits<A_test>
{
typedef void(T*F)();
static const F f = &A_test::A_test_f;
};
int main ()
{
B<A_test> b;
b.b_f(); // will invoke "A_test::A_test_f()" rather than "A_test::f()".
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
ok, lets say I have this:
class A:
{
Public:
int dd;
}
Ok, then I have this class:
class B:
{
Public:
void sss(){ ff=dd; }
int ff;
}
Ok, the problem is that class B doesn't know what dd is. How can I make class B know it?
It's public: and not Public:.
Because dd is part of A, you need an instance of A to access dd.
The two classes aren't related in any way; since B does not have access to any A objects it can't take the value of its members.
If you were to pass an A object to the B constructor, either by value, reference, or pointer, you could access its dd member since you made it public.
You need to have an instance of A, and pass it to the sss method in order to access this data:
void sss(A a) { ff = a.dd; }
If you want to have only one copy of dd, rather than a single copy per instance of A, then you'll have to make dd static:
class A
{
public:
static int dd;
};
class B
{
public:
void sss() { ff = A::dd; }
int ff;
};
Maybe by passing in an A instance?
class B:
{
Public:
void sss(const A& a){ ff=a.dd; }
int ff;
}
Your code does not look like C++ but I will try to answer your question.
There would be several possibilities to do what you want. I just pick one which is easy to understand.
Do someting like this:
class B
{
public:
void sss() { ff = a.dd; }
int ff;
private:
A a;
};
However if you do not tell me what you really want to achieve with that class i.e. which responsibilites the class has this will not help you much.
The code that you present, ...
class A:
{
Public:
int dd;
}
class B:
{
Public:
void sss(){ ff=dd; }
int ff;
}
... is not valid C++.
You can find that out easily enough by trying to compile it. Then the compiler will complain about a lot of irrelevant things, but its first message will be related to the extraneous colon after A. When you remove that and compile again, its first message will be related to Public, as opposed to correct public (lowercase). So on.
Syntacically correct code (that will still produce a compilation error, but not about the basic syntax):
class A
{
public:
int dd;
};
class B
{
public:
void sss(){ ff=dd; }
int ff;
};
Imagine that you create five instances of class A, named a1, a2, a3, a4, and a5. Each such instance has a member dd, so you can refer to these five members as a1.dd, a2.dd, a3.dd, a4.dd, and a5.dd.
Now you create a B instance, naming it 'b'. And you call b.sss(). And that member function effectively does b.ff=dd. Or it would, had it been meaningful and accepted by the compiler. But it can't, for which of a1.dd, a2.dd, a3.dd, a4.dd, and a5.dd is being referred to?
So, since this is a very basic concept in C++, you need a good C++ textbook, such as Bjarne's latest, and start from the beginning.
Alternatively, since C++ is a very complicated programming language, it's probably even better to start with some simpler language, like Java, or even simpler, like JavaScript or Python. I recommend Python. It's very different from C++ in the details, but both languages are "conventional" programming languages. Using Python you'll learn about decision constructs and functions and things, including classes versus instances.
Cheers & hth.,