I have to write definition of the code below. I undarstand some basics of OOP Cpp, I know what is *x or &x, but that's not enough... The main fact is that i cant understand line B* p = new D, m, *k; i cant understand what m and *k stand for.
class B {
public:
virtual void msg() { cout << "classB"; }
};
class D: public B {
public:
virtual void msg() { cout << "classD"; }
};
int main() {
B* p = new D, m, *k;
p->msg(); k = &m; k->msg();
. . .
}
Help, if you can explain how (and why so) this code will work.
thanks, for your time.
It declares multiple variables at once. This is basically the same as:
B *p = new D;
B m;
B *k;
So p is a pointer to an instance of D allocated with new. m is a local instance of class B and k is a pointer to B that is later assigned to point at m.
The msg function is called on both allocated objects via the pointers p and k.
Note that * applies to each variable declaration separately. So B* a, b; doesn't declare two pointers, but instead declares one pointer and one local object. This is the reason, that many people prefer to write the * directly in front of the variable name: B *a, b makes this a bit more obvious.
In C++ you can declare more then one variable in one statement. Therefore B* p = new D, m, *k; declares the variables p, m and k. The * for pointer declarations binds to the variable name, therefore it's basically identical to
B* p = new D;
B m;
B* k;
Nothing fancy, it's just plain old C.
B* p = new D, m, *k;
is just shortcut for:
B* p = new D;
B m;
B* k;
p is a pointer to an object of the class B (or D, because it is a child of the class B). p->msg(); is similar to (*p).msg();. m is an object of the class B, so we can get pointer to it by & operator and store it in k (which is a pointer to an object of the class B).
And
B* p = new D, m, *k;
is just
B* p = new D;
B m;
B* k;
Notice: you should put * if it is needed each time
Related
Imagine that I have an object A that refers to an object B through its address. The address to B is given in the constructor of A.
Some methods of A modify B, other do not.
Here is a very simple illustration :
class B {
public :
void f1() const;
void f2();
};
class A {
public :
A(B * pb) {m_pb=pb;}
void g1() {m_pb->f1();} // g1 do not modify *m_pb
void g2() {m_pb->f2();} // g2 do modify *m_pb
private :
B * m_pb;
}
Now, imagine that in some part of my code, I have a variable whose type is const B &. I want to create an object A to call the g1 method that do not modify the object B. But I cannot construct an object A at all.
One solution would be to create 2 classes A1 and A2 with A1 referencing a const B * and defining only method g1 while A2 would reference a B * and would define both g1 and g2. (g1 would be defined in 2 different places). I don't find this solution very elegant.
I wonder whether there is a way to explain to the compilator that :
const A won't modify the object B that it is referring.So a const A objet can be constructed using a const B object.
I wonder whether there is a way to explain to the compilator that : const A won't modify the object B that it is referring.So a const A objet can be constructed using a const B object.
What you want is const constructor and there isn't one. But you can avoid duplicating the interface with inheritance:
struct B{
void f1() const{}
void f2() {}
};
class constA
{
public:
constA(const B* b):b(b){}
// Should be const as it does not changes `constA` object.
void g1() const {b->f1();}
// No harm in this, but can be protected if you want
const B* getB() const { return b;}
private:
const B* b;
};
class A : public constA
{
public:
A(B* b):constA(b){}
void g2() const { getMutableB()->f2();}
private:
B* getMutableB() const { return const_cast<B*>(getB());}
};
int main()
{
B b;
const B cb;
A a(&b);
a.g2();
a.g1();
constA ca(&cb);
ca.g1();
//ca.g2();
constA ca2(&b);
ca.g1();
//ca.g2();
}
EDIT: (Per request from #formerlyknownas_463035818 with which I agree ) Quick refresher on const_cast:
int main()
{
const int x = 5;
int y = 5;
const int* c_ptr = &x;
//'ptr' is valid object with known value.
int* ptr = const_cast<int*>(c_ptr);
// Is valid because '*ptr' is not modified
int value = *ptr;
// Undefined behaviour because '*ptr' is const object.
*ptr = 5;
const int* c_ptr2 = &y;
//'ptr2' is valid object with known value.
int* ptr2 = const_cast<int*>(c_ptr2);
// Is valid because '*ptr2' is not modified
int value = *ptr2;
// Is valid because '*ptr2' is not a const object.
*ptr2 = 5;
}
Given that A only has non-const B constructor then getB() always returns a pointer to a object that is not const. So the second part of the above example applies and everything is safe.
Note that const casting const B in order to pass it to A would produce UB when calling g2 but that is true for all B* ptrs with unknown origin and there's nothing A class can do about it.
I have a class:
class C {
public:
C(): _a(a++){}
private:
static int a;
int _a;
};
int C::a = 0;
C c = C(); // c._a is 0
C d = C(); // d._a is 1
C e = C(); // e._a is 2
This works out as I'd expect: a and obj._a increment by 1. But if I assign c, d, and e to an unordered_map, they increment by 2:
unordered_map<int, C> map;
C c = C(); // c._a is 0
map[0] = c;
C d = C(); // d._a is 2
map[1] = d;
C e = C(); // e._a is 4
map[2] = e;
How can I assign c, d, and e to map and still make the static int a increment by 1?
The problem comes from your map. When you access map[0], the map will look for the entry 0 and if it does not exists, will instantiate it and returns to you a reference to the new instance.
Try using map.emplace(0, c) instead to add an item in your map.
Your problem is that the expression map[0] is creating a default constructed 'C' (and incrementing the counter), and then that object is assigned to.
The solution is to directly insert the object in the map with:
map.insert({0,c});
For example, I have the following codes:
int a = 1;
int b = 2;
int *c = &a;
int &d = *c;
c = &b;
d++;
What is behaviour of line 4? If i want a reference to a pointer,is it correct to use
int *&e = c;
Is there any reason why to choose a reference to a pointer?
This declaration
int &d = *c;
declares a reference that refers the object pointed to by pointer c.
When this declaration was executed pointer c pointed to object a
int *c = &a;
So the referecne d refers object a. References may not be reassigned. They shall be initialized when they are declared.
Thus the expression in statement
d++;
increases object a.
You may declare a reference to a pointer.
This declaration
int *&e = c;
is valid.
Constant references can be bound to a temporary object. You may not take an address of a temporary object. Refrences alow to use more simple expressions.
Consider for example a simplified function swap that swaps two integers.
Using pointers the function would look like
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
and it could be called like
int a = 5;
int b = 10;
swap( &a, &b );
Using references you could write the function the following way
void swap( int &a, int &b )
{
int tmp = a;
a = b;
b = tmp;
}
and its call would look simpler than the call of the function with pointers.
int a = 5;
int b = 10;
swap( a, b );
regarding the meaning of line 4
int a = 1;
int*c = &a; // okay: pointer to int, points to a
int&d = *c; // okay; reference to int, refers to *c=a;
A reference to a pointer is useful as argument to a function that may alter its value (=address pointed to), for example
void allocate(int*&p)
{ p=new int[10]; }
I saw an online C++ test regarding the constructor. I can figure out most of the answers but am puzzled by some in the following. Hope someone can help me out.
Here's the example.
#include <iostream>
class A {
public:
A(int n = 0) : m_n(n) {
std::cout << 'd';
}
A(const A& a) : m_n(a.m_n) {
std::cout << 'c';
}
private:
int m_n;
};
void f(const A &a1, const A &a2 = A())
{
}
int main() {
A a(2), b;
const A c(a), &d = c, e = b;
b = d;
A *p = new A(c), *q = &a;
static_cast<void>(q);
delete p;
f(3);
std::cout << std::endl;
return 0;
}
What I don't really get is why "&d = c" doesn't output anything. Also adding another overloading constructor like A(const A *a) : m_n(a->m_n) { std::cout << 'b'; } doesn't output anything either for *q = &a. So what can I do to make it work?
Many thanks for any advice. I am very curious about this.
There's no output for these because d and q are not of type A, i.e. they are not A objects. d is a reference to A and q is a pointer to A. Initialising a reference and initialising or assigning a pointer does not manipulate the referred-to/pointed-to A object at all, hence no output.
To address your question - there is nothing to "make work," it works just as it should.
That to be more clear I will rewrite this statement
const A c(a), &d = c, e = b;
as
const A c(a);
const A &d = c;
Here d is declared as a reference to an object of type A. It does not create a new object. It refers to an object that is already created. In this case d referes to c. In fact d is simply an alias for object c.
This code snippet
A *p = new A(c), *q = &a;
also can be rewritten for simplicity
A *q = &a;
In this statement pointer q is simply assigned by the address of a. Neither object is created. Simply q now points to already created early object a.
&d = c doesn't output anything because you're not calling the constructor.
If we expand that code fragment a bit...
A &d = c
What your code is saying there is "declare d to be a reference to an object of type A, which points to c". Because you're creating a reference, you're not calling the constructor, c and d are the same object.
The same applies to q, but instead of creating a reference, you're creating a pointer and assigning it the address of an existing instance of type A. The constructor isn't called because you're not creating a separate object, you're linking to an existing one.
The following code is one that I written for myself in order to test how pointers and vectors work.
I am very new to C++.
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
//Create the integer pointer vector, and clean it to initialize
vector<int *> lol;
lol.clear();
//Create the pointers and point them to 1,2,3
int a1=1, a2=2, a3=3;
int* a, b, c;
a=&a1;
b=&a2;
c=&a3;
//Put the pointers into the vector
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
//Return the value of the middle pointer
cout << *lol[1];
}
I get a whole wall of errors while compiling.
Can anyone help? Bear in mind I can only understand novice.
The problem is with this line:
int* a, b, c;
a is int*, but b and c are just ints.
int *a, *b, *c;
Would make it all int*s.
int* a;
int* b
int* c;
does the same thing, but with clearer intentions of declaring three int*s.
See: Placement of the asterisk in pointer declarations
UPDATE: Even better:
int* a = &a1;
int* b = &a2;
int* c = &a3;
Whenever you can, don't separate variable initialization and its declaration.
When declaring multiple pointers on one line, you have to specify the * symbol in front of each pointer variable.
int * a, b, c;
should be :
int *a, *b, *c;
The line :
int * a, b, c;
is interpreted as :
int *a;
int b;
int c;
If you declare variables, do not declare multiple variables on the same line.
What you thought you did was to declare three pointers to int. What you did, was to declare three ints, one of them a pointer:
int* a, b, c;
means
int *a; int b; int c;
Think of the * as belonging to the variable name. Unintuitive, but that's the way the language works.
You want to declare all of the three as pointers:
int* a;
int* b;
int* c;
Change this
int* a, b, c;
to
int *a, *b, *c;
In your declaration you are declaring
a as pointer to int
b as int
c as int
The main problem, as others already noted, are the definitions here:
int* a, b, c;
Basically, only a is an int *; b and c are just ints.
It's just better to have one variable definition per line:
int* a = &a1;
int* b = &a2;
int* c = &a3;
If you use these raw pointers, and if for some reason you want to first define them and then assign their values later, consider at least initializing them to nullptr (or NULL if you are using C++98/03):
// Initialize to NULL/nullptr, to avoid pointers pointing to junk memory
int* a = nullptr;
int* b = nullptr;
int* c = nullptr;
....
// assign proper values to pointers...
Moreover, there are also other notes that can be made for your code:
int main(void)
Since this is C++ - not C - you can omit the (void), and just use () instead:
int main()
When you create the vector:
vector<int *> lol;
lol.clear();
you don't need to call its clear() method after the vector definition: in fact, vector's default constructor (implicitly called by the compiler when you defined the vector in the first line) has already initialized the vector to be an empty vector.
This is just fine:
vector<int *> lol; // Creates an empty vector
Considering these notes, your code can be written something like this:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int *> lol;
int a1 = 1;
int a2 = 2;
int a3 = 3;
int * a = &a1;
int * b = &a2;
int * c = &a3;
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
cout << *lol[1] << endl;
}
First problem is at declaration of pointers
int* a, b, c;
This will create a as pointer and b & c as int.
Use declaration like
int* a,*b,*c;
And While accessing the elements of vector use .at() method of vector.
cout << *lol.at(0) << endl;