I've got weird thing which, by my experience, I can call bug in C++. When I call this program:
#include <iostream>
using namespace std;
class foo {
public:
int a;
foo(int a = 0) : a(a) {}
} a1;
class bar {
foo a;
public:
bar(foo a = a1) : a(a) {
a.a = 1;
cout << a.a << endl;
}
void print_a() {
cout << a.a << endl;
}
};
int main() {
bar zz;
zz.print_a();
a1.a = 2;
bar zz1;
zz1.print_a();
}
The output is:
1
0
1
2
I do expect to be able to change values of internal members of my class, like the a value of the object of foo class inside bar class. When I change the a.a value in bar constructor, it looks like I changed only local variable. What is the mechanism of this process? C++ does not treat variables inside its class as constant parameters, because I can as well get counter which is changed by methods. But when counter is one class more deeper, the structure seems to collapse.
Within the constructor body, argument names hide member names, so as you surmised, you're modifying the function argument a, not the member a.
You can refer to the member as this->a or bar::a to disambiguate, if you don't want to rename either variable.
Related
For certain reasons, I want to have multiple instances of class A all have access to a single instance of class B. B has public member functions that allow objects of A to get data from B, but not to change it. I'm trying to do this by declaring an object of B in my main function, then passing it to the constructor when I declare objects of type A.
void main () {
B obj_b;
A A1(obj_b);
A A2(obj_b);
A A3(obj_b);
cout << A1.getfoo() << endl;
cout << A2.getfoo() << endl;
count << A3.getfoo() << endl;
}
class B{
private:
int foo = 9;
public:
int getfoo(){return foo;}
};
class A {
private:
B *bptr;
public:
A(B b){ this->bptr = &b; }
int getfoo(){ return bptr->getfoo(); }
};
This compiles and runs, but I get very weird results. The return values from getfoo are sometimes correct sometimes incorrect. Am I handling the pointers incorrectly? Is there a better way to do this?
In the A constructor, the argument b is a local variable, its life-time ends when the constructor function ends. You can't save a pointer to it, that pointer will become invalid immediately.
Either use smart pointers, or use a reference and constructor initializer lists:
class A
{
public:
// Pass by reference
A(B& b)
: b{ b } // Initialize the member variable b with the argument b
{
// Empty body
}
private:
B& b; // Reference to a B object
};
This question already has answers here:
C++ Default Constructor Called
(3 answers)
Closed 4 years ago.
Okay, first off this is a trivial question, but nonetheless it's bugging me. Disclaimer: I'm not a compiler engineer. But it seems to me the compiler in this case is requiring a constructor that is really not necessary. Code below; why is the B constructor that takes no parameters and does nothing being called when an already instantiated object of it's class is being passed to the constructor of another class? For reference I'm using g++ (GCC) 5.3.0 and have not tried it with any other compilers (and yeah I know GCC is not without its quirks):
#include <iostream>
namespace I_DO_NOT_GET_IT
{
class A;
class B;
}
class B
{
public:
B()
{
std::cout << "\nWhy am I here?\n\n";
}
B(const int aInt, const char * aChar)
{
mInt = aInt;
mChar = aChar;
}
void identify()
{
std::cout << "\nI am an object of class B, owned by class A\n"
<< "my integer data is "
<< mInt
<< " and my character data is \""
<< mChar
<< "\"\n\n";
}
int mInt;
const char * mChar;
};
class A
{
public:
A(B an_instantiated_object_of_class_B)
{
b = an_instantiated_object_of_class_B;
}
// class A owns an object of class B
B b;
};
int main()
{
// create an object of class B
B b(1, "text");
// pass the B object to A, which uses it to instantiate its B object
// in the A constructor.
A a = B(b);
// Have A's B object describe itself
a.b.identify();
return 0;
}
A(B an_instantiated_object_of_class_B)
{
b = an_instantiated_object_of_class_B;
}
The default constructor of B is used when A::b is created before the constructors body runs, where an assignment b = ... occurs.
Use the initialization list instead:
A(B an_instantiated_object_of_class_B)
: b{ an_instantiated_object_of_class_B }
{
}
btw, your namespace I_DO_NOT_GET_IT is pointless. The declarations in there have nothing to do with your classes A and B.
I don't understand what is wrong with this code. It looks like an incredible trap !
This code :
class Foo
{
public:
virtual double foo(double x) const = 0;
double foo(int x) const { return (double)(x + x); }
};
class Bar : public Foo
{
public:
virtual double foo(double x) const { return x * x; }
};
int main()
{
Bar* b = new Bar;
Foo* f = b;
std::cout << b->foo(3) << " " << f->foo(3) << std::endl;
std::cout << b->foo(5.0) << " " << f->foo(5.0) << std::endl;
return 0;
}
prints the following output :
9 6
25 25
I deduce that Bar::foo(double) const is called with an implicit cast when the type of the pointer is Bar*. But why such a thing is possible without any warning ?
I work with GCC 4.7.2. I compiled with g++ -Wall foobar.cpp -o foobar.exe
This is due to name hiding.
When you declare a function called foo in Bar, you hide all declarations with the same name in Foo.
As such, when the static type of the pointer is Bar, the compiler only finds the version in Bar which takes a double, so it implicitly converts the int to satisfy this.
If you want the int version in Foo to be visible, add a using declaration:
class Bar : public Foo
{
public:
using Foo::foo;
// ^^ makes the versions in Foo visible
virtual double foo(double x) const { return x * x; }
};
When the type is Bar*, only one version of the method is visible, the one with the double parameter.
Base methods with the same name (but different signature) are hidden.
To make them available, you can use using Foo::foo in the derived class.
Depending on your compiler, I think you might also get warnings regarding the implicit conversion, or the fact that you apparently want to call a hidden method.
In Foo there are two overloads of foo, one that takes a double and another that takes an int.
In Bar there is one overload of foo, the one that takes a double. This overload hides all functions with the same name from the base classes. This is called name hiding.
A fix would be to employ using declaration to bring the other foo overloads from the base class in scope of Foo derived class:
class Bar : public Foo
{
public:
using Foo::foo;
virtual double foo(double x) const { return x * x; }
};
I've read about class with no name...
Got that
class
{
int i;
};
is not valied while
class
{
int i;
}A;
is valid.
But how to have a: 1) constructor and :2) destructor and: 3) how to pass as an argument???
If the class is unnamed then it can't have a custom constructor/destructor (although the compiler will generate the usual default ones for you). That means you can't pass an argument to it at construction. However, there's probably nothing stopping you from either (1) adding one or methods to the class to pass data to it after construction, or (2) giving the class a name in the first place.
The second thing is valid, but you cannot access the member i since it will be private. It is valid only because You have created an object A of that class type.
To have a constructor, I think you have to give the class a name. Use this:
class myclass
{
int i;
public:
myclass(int a) //This is the constructor
{
i = a;
}
~myclass() //This is the destructor
{
//Whatever you want to do on destroying the object
}
};
and instantiate that class as follows:
myclass A(10);
or similarly.
Note: This is just my interpretation, it can be done in many other ways.
You are doomed using the class locally and accessing it through the local object A, only.
You can use it in a template, though:
template <typename T>
inline void print(const T& a) {
std::cout << a.x << std::endl;
}
int main()
{
class {
public: int x;
} a;
a.x = 1;
print(a);
}
So say I have 3 classes: Base, A, and B.
Base is a base class for both class A and class B.
Base has a variable val that A and B can access.
How would I get it to work where I can set the val variable through class A, and it is reflected in class B?
For example:
I know this code below won't work because I am creating an OBJECT of the type a and b.
What I want to do is to simply have a and b share the same variable so that whenever a does something to it, it is reflected in b.
a aa;
b bb;
aa.SetVal(50000);
cout << aa.GetVal() << endl;
cout << bb.GetVal() << endl;
In the end I'd want both cout lines to print out 50000.
EDIT: The classes A and B will be doing different operations and just need to be able to access/change the val variable in base
You could make the member a static member of the base class, then all derived classes could access it, however any object of a derived that changes the static member would change it for every other object.
class Base
{
public:
int GetVal()
{
return val;
}
void SetVal( int newVal )
{
val = newVal;
}
private:
static int val;
};
// Need to instantiate the static variable somewhere
int Base::val = 0;
class A : public Base
{};
class B : public Base
{};
class Base {
static int value;
public:
virtual ~Base() { }
void setVal(const int& val) {
value = val;
}
int getVal() const {
return value;
}
};
int Base::value = 0;
class A : public Base {
};
class B : public Base {
};
#include <iostream>
int main() {
A a;
B b;
a.setVal(20);
std::cout << b.getVal(); // 20
}
That's a job for references, not for classes. Just have one class X and create a reference to the object:
X aa;
X& bb = aa;
aa.SetVal(50000);
std::cout << aa.GetVal() << std::endl;
std::cout << bb.GetVal() << std::endl;
The output will be:
50000
50000
Remember to always use the right tool for the job and keep things simple.
The main goal is that those two classes will be doing different things but will need to be able to access and share a single variable.
An idea to solve this is to extract the common variable in another class, namely S, which will be passed to A and B like this:
std::shared_ptr<S> s = new S();
A aa(s);
B bb(s)
Now, both aa and bb share the same S object and can modify it very easily. Notice that the constructor of both A and B should store the std::shared_ptr<S> as well:
class A { // and B
private:
std::shared_ptr<S> s;
public:
A(std::shared_ptr<S> as) : s(as) {}
};
The variable s will last as long as any of aa and bb is alive: when both aa and bb gets deallocated or go out of scope, the variable s will be deallocated as well.
If the type of the common variable should be on the stack, you can also just use references, but watch out for the lifetime of aa, bb and that variable:
int s = 0;
A aa(s);
B bb(s);
with:
class A { // and B
private:
int& s; // or any other type
public:
A(int& as) : s(as) {}
};
But as a general rule of thumb I'd avoid shared state between objects. Most of the time, depending on the context, you can refactor your code and get rid of the shared dependency.
If the shared value is static in the base class, then all instances of derived classes will see exactly that one base class member.
If the value is not static, then each instance of a class will have its own copy whether or not the value is in a base class.
Not sure I understand what you are trying to do. Do you want all instances of A and B to share the same value? if so, declare it as static in the base class.
if not, how do you want to choose which one will share the value?