C++ using 'this' keyword in member initialization list - c++

I was writing an Integer struct
struct Integer
{
int value;
Integer(int value_) : value(_value){ }
};
This works fine but instead I wanted to use value name for the parameter too and this causes a name clash. That's why I tried to use this keyword like below
struct Integer
{
int value;
Integer(int value) : this->value(value){ }
};
But I got an error and I don't seem to understand the problem here. I would be very happy to learn. Thanks for your answers.

This works fine but instead I wanted to use value name for the parameter too and this causes a name clash.
No it doesn't.
Integer(int value) : value(value){ }
This is just fine (if a little confusing to some).
It is simply not permitted in the language grammar to write this-> there, probably because it would make no sense to specify any other object: the this-> is implicitly done for you.

The standard way is to write
struct Integer
{
int value;
Integer(int value) : value(value){ }
};
In the initializer list : value(value), the first value refers to the member (because that's what a member initializer initializes), while the second value refers to the constructor argument (because that's an expression, and the name in an expression is looked up by the ordinary rules).

As other answers already mentioned, it is not defined in the C++grammer / syntax.
See it here.
And there is no need to specify this. To disambiguate class vs. member you don't use this, you use the scope resoultion operator.
See this (strange) example:
#include <iostream>
class A{
public:
A(int a){
std::cout << "A("<< a << ")\n";
}
A(){
std::cout << "A()\n";
}
};
class B : public A
{
public:
int A;
B(int a) : A::A(42), A(a)
{}
};
int main()
{
B b = 12;
std::cout << b.A;
return 0;
}
And of course this already exists:
#include <iostream>
class B;
class A{
public:
A(int a){
std::cout << "A("<< a << ")\n";
}
A(){
std::cout << "A()\n";
}
A(B& b);
};
class B : public A
{
public:
int A;
B(int a) : A::A(*this), A(a)
{}
};
inline A::A(B& b){
std::cout << "A(B&)\n";
}
int main()
{
B b = 12;
std::cout << b.A;
return 0;
}

Related

Question about C++ call virtual function implemented in base from derived class

What is wrong with the following code?
struct A {
virtual int hash() const = 0;
virtual int hash(int x) const = 0;
};
struct B : public A {
int hash() const final {
return 10;
};
int hash(int x) const override {
return 10;
};
};
struct C : public B {
int hash(int x) const override {
return x;
}
};
#include <iostream>
int main() {
C a;
std::cout << a.hash() << std::endl;
std::cout << a.hash(20) << std::endl;
return 0;
}
I got compile error with the following error message
xx.cc:26:23: error: too few arguments to function call, single argument 'x' was
not specified
std::cout << a.hash() << std::endl;
~~~~~~ ^
xx.cc:17:3: note: 'hash' declared here
int hash(int x) const override {
^
1 error generated.
This is name hiding issue. According to the rule of name lookup,
(emphasis mine)
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
So C::hash hides the name from the base class.
You can apply using to introduce the name into the class C scope.
struct C : public B {
using B::hash;
int hash(int x) const override {
return x;
}
};
Yeah, you have to redefine the overload within the derived class.
struct C : public B {
int hash(int x) const override {
return x;
}
int hash() const override {
return B::hash();
}
};
Or alternatively call via a reference to B
int main() {
C a;
B& b = a;
std::cout << b.hash() << std::endl;
std::cout << b.hash(20) << std::endl;
return 0;
}

How to pass an unrelated class in a constructor of another class?

Extra line of code can be added only to the place where '>>' sign is present.
My targeted input and output is as follows:
Input: 15
Output : 16:15:17:16:
I need help only in
cout << r.get() << ":";
part. An explanation would be helpful.
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ai) : i(ai) {}
int get() const { return i; }
void update() { ++i; }
};
class B {
int i;
public:
B(int ai) : i(ai) {}
int get() const { return i; }
//>>
operator A() {return A(i);}
void update() { ++i; }
}; // End of class B
int main() {
int i;
cin >> i;
A a(i++);
B b(i);
const B &r = static_cast<B>(a);
a.update();
cout << a.get() << ":";
cout << r.get() << ":";
const A &s = static_cast<A>(b);
b.update();
cout << b.get() << ":";
cout << s.get() << ":";
return 0;
}
You cannot solve the asker's problem by modifying a conversion operator in class B. B's conversion operators only tell the constructor how to make another datatype out of a B. To do this with a conversion operator, the operator needs to be in class A.
class B; // forward declaration of B so that A knows it exists
class A
{
int i;
public:
A(int ai) :
i(ai)
{
}
int get() const
{
return i;
}
void update()
{
++i;
}
operator B(); // cannot implement the function yet because we do not have a
// complete definition of B. Without a definition of B we cannot
// construct B excluding forward defined helper functions that are
// implemented later, gaining us nothing.
};
Then later after B is fully defined,
A::operator B()
{
return B(i); // now we have enough information to construct a B
}
Note: We can reduce some of this messiness by moving the definition of B to before the definition of A. Unfortunately this makes the code required to support the
const A &s = static_cast<A>(b);
that comes later in the code require forward declaration of A and the implementation of the B to A conversion operator outside the definition of B.
An alternative is adding a constructor to B that takes an A
B::B(const A& a): i(a.get())
{
}
and vice-versa for A.

How to get n-th attribute of class in C++

With a normal class. For example:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
}
We can do:
A x;
x.a = 1;
x.b = "hello";
But now I don't want to do like above. I want to access n_index-th attribute of object. For example pseudo like x.get<2>() (or x.set<2>(...)) like x.b.
How can do that? Have any template for that.
Beside if I want code like that
int number = 2;
x.get<number>()
Any problem with constexpr?
I think the closest you can get is using boost::fusion.
An example would be
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/int.hpp>
#include <iostream>
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
BOOST_FUSION_ADAPT_STRUCT(A,
(int, a)
(std::string, b)
)
using namespace boost::fusion;
int main()
{
A x;
x.a = 1;
x.b = "hello";
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
at<boost::mpl::int_<0>>(x) = 5;
at<boost::mpl::int_<1>>(x) = std::string("World");
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
}
If you want to set several values at the same time when you create the object, you could use a multi-parameter constructor. For example, let's imagine you have this:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
You could add a constructor that sets a and b:
class A {
public:
int a;
std::string b;
A() {}
A(int a, std::string b) {
this->a = a;
this->b = b;
}
~A() {}
};
That way, you can create your object and set a and b with :
A a = A(1, "hello");
There is no ready-made way of setting the n-th attribute of your object. You could make one, but I would very, very highly recommend that you don't. Like I said above, if you reorder your attributes, then you will have to rework everything.
If you really, really want to make your life very, very, very much harder, a very ugly and error-prone way of doing this would be like :
template<class T>
void A::setNth(int nth, const T& value) {
switch (nth) {
case 1: a = value; break;
case 2: b = value; break;
// You should #include <stdexcept> to use runtime_error, or you could handle the exception in some other way.
default: throw std::runtime_error("A::setNthAttribute : Value of nth is out of bounds.");
}
}
For the getter:
template<class T>
void A::getNth(int nth, T& valueOut) {
switch (nth) {
case 1: valueOut = a; break;
case 2: valueOut = b; break;
default: throw std::runtime_error("A::getNthAttribute : Value of nth is out of bounds.");
}
}
You would use these methods like this:
A a;
a.setNth(1, 2); // put 2 into a
int i;
a.getNth(1, i); // put a into i
Just writing this code send shivers down my spine. Please, never write what I just wrote. Chuck Norris will kill yoU agfh
86sd asdsa dDASD8!4.
What you are considering is in fact possible, but a bit of a headache. I would approach it by creating a template getter and setter for every member that one can set or get, and then having a template method that takes an int and sets or gets the appropriate property. The getters/setters would have to be specialized for the correct type, and throw an error for other types. This method would have to use a switch to return the right member:
class bar {
private:
int a;
std::string b;
template<T>
T getA() {
// error
}
template<T>
T getB() {
// error
}
template<T>
void setA(const T& A) {
// error
}
template<T>
void setB(const T& B) {
// error
}
template <> std::string getB(); // specialization
template <> int getA();
template <> void setB(const std::string&);
template <> void setA(int);
public:
template<T>
T get(int what) {
switch(what) {
case 1:
return getA();
case 2:
return getB();
default:
// handle error here
break;
}
}
template<T>
void set(int what, const T& t) {
switch(what) {
case 1:
return setA<T>(t);
case 2:
return setB<T>(t);
default:
// handle error here
break;
}
}
};
bar b;
b.set<std::string>(2, "foo");
auto str = b.get<std::string>(2);
Here's an elaborate way to accomplish what you want.
#include <iostream>
#include <string>
// A namespace explicitly defined for class A.
namespace A_NS
{
// A template for members of A.
template <int> struct Member;
// Specialization for the first member.
template <> struct Member<1>
{
using type = int;
type var;
};
// Specialization for the second member.
template <> struct Member<2>
{
using type = std::string;
type var;
};
}
class A {
public:
A() {}
~A() {}
template <int N> typename A_NS::Member<N>::type get() const
{
return static_cast<A_NS::Member<N> const&>(members).var;
}
template <int N> void set(typename A_NS::Member<N>::type const& in)
{
static_cast<A_NS::Member<N>&>(members).var = in;
}
private:
// Define a type for the member variables.
struct Members : A_NS::Member<1>, A_NS::Member<2> {};
// The member variables.
Members members;
};
int main()
{
A a;
a.set<1>(10);
a.set<2>("test");
std::cout << a.get<1>() << ", " << a.get<2>() << std::endl;
}
Output:
10, test

Getting the address of an rvalue

class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(MyClass* a) { std::cout << a->a << std::endl; }
int main() {
print(&static_cast<MyClass&&>(MyClass(1337)));
return 0;
}
This doesn't work with GCC 4.6, while it used to work in a previous version.
Now it says: taking address of xvalue (rvalue reference).
Is there any way to securely pass the address of an rvalue to another function?
is: there is anyway to securely pass an rvalue reference (a.k.a. address of temporary) to another function without boringly storing it in a variable just to do that?
Yes, there is, like in the next example :
#include <iostream>
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
void print(MyClass&& a) { std::cout << a.a << std::endl; }
int main() {
print( MyClass(1337) );
}
An rvalue does not necessarily have an address. However, there is a way to get the effect you want, by exploiting the fact that binding an rvalue to a reference forces it to be a temporary (which does have an address):
template<typename T> T *addressOfTemporary(T &&v) { return &v; }
Inside this function, v is an lvalue (despite being declared as T&&), so can have its address taken. You can use this function as follows:
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(MyClass* a) { std::cout << a->a << std::endl; }
int main() {
print(addressOfTemporary(MyClass(1337)));
return 0;
}
Note that the temporary's lifetime ends at the end of the full-expression (the print(...) expression, in this case), so you will need to be careful that the pointer is not used past that point.
If you don't particualrly need to print rvalues only, you can use a standard const reference instead:
class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};
#include <iostream>
void print(const MyClass& a)
{ std::cout << a.a << std::endl; }
int main() {
print(MyClass(1337));
return 0;
}

How to set parent members when creating inherited struct in C++

I have a struct type A, which I could instantiate with A(p_a1, p_a2) and a struct type B, which inherits from A, that I can instantiate with B(p_b1, p_b2, p_b3).
Is there a standard way to create a B instance while also setting p_a1 and p_a2? Would I just set them after creating the B instance with b.p_a1 = v_a1; b.p_a2 = v_a2?
(Sorry for any incorrect use of terminology. I don't have much experience with C++.)
Thanks
You are looking for a C++ feature named constructor initialization lists. This example should clarify it to you:
#include <iostream>
class Foo
{
public:
Foo( int x )
{
std::cout << "Foo's constructor "
<< "called with "
<< x
<< std::endl;
}
};
class Bar : public Foo
{
public:
Bar(int x, int y, int z) : Foo( x ) // construct the Foo part of Bar
{
std::cout << "Bar's constructor" << std::endl;
}
};
int main()
{
Bar stool(10,11,12);
}
What you intend to do is achievable using initialization lists and can be done as follows:
struct A
{
A(int _a):a(_a){}
};
struct B : public A
{
B(int _a, int _b):A(a), b(_b){}
} ;
In the sample code which you have provided, what you are doing in these lines b.p_a1 = v_a1; b.p_a2 = v_a2 is called assignment. While the former will invoke just the right constructor, latter would invoke the default constructor.
Try the following
struct A {
int _a1;
int _a2;
A(int a1, int a2); //assume it is defined
};
struct B : public A {
int _b1;
B(int p1, int p2, int p3);
};
B(int p1, int p2, int p3)
: A(p1,p1), // <<== This is where parent member variables will be initialized.
_b1(p3) //or some other way to populate _b1
{ }
google "C++ constructor initialization list"