Function compiling even though it doesn't accept integer [duplicate] - c++

This question already has answers here:
What is a converting constructor in C++ ? What is it for?
(3 answers)
Closed 3 years ago.
I am confused how can we pass an integer when the parameter of a function only accept a class of type enemy ( void foo(const Enemy& inKlep ).
Yet when we pass to it an int (300) it compiles. Why is this?
#include <iostream>
using namespace std;
class Enemy {
public:
Enemy() { cout << "E ctor" << endl; }
Enemy(int i) { cout << "E ctor " << i << endl; }
Enemy(const Enemy& src) {cout << "E copy ctor"<< endl;}
Enemy& operator=(const Enemy& rhs) {cout<<"E="<<endl;}
virtual ~Enemy() { cout << "E dtor" << endl; }
void hornet(int i=7) const { // Not virtual!
cout << "E::hornet " << i << endl;
}
};
class Scott : public Enemy {
public:
Scott() : Enemy(1) { cout << "S ctor" << endl; }
Scott& operator=(const Scott& rhs) {cout<<"S="<<endl;}
virtual ~Scott() { cout << "S dtor" << endl; }
void hornet(int i=7) const {
cout<<"S::hornet " << i << endl;
}
};
void foo(const Enemy& inKlep) {
Enemy theEnemy;
inKlep.hornet(2);
}
int main(int argc, char** argv) {
foo(300);
cout << "Done!" << endl; // Don't forget me!
}

In C++, it is valid code for an input parameter to implicitly construct an object if the function expects an object that can be constructed from that parameter. So, for example:
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
func(5); //Valid; will print '5' to the console
}
If you don't want to allow this, you need to add the keyword explicit to the constructor to prevent this.
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
explicit CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
//func(5); //Invalid; will cause a compile-time error
func(CustomInt(5)); //Valid; will print '5' to the console
}

Related

Calling inherited functions and overriding behavior in c++

Why does this give this error -
'void D::func(const D &)': cannot convert argument 1 from 'const C' to 'const D &'
How to correct this, I want to call Base's func from Derived's func but note func is a friend function?
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1)
{
cout << "in C's func" << endl;
}
};
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
func(static_cast<const C&>(abc));
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}
why does this similar e.g. work though -
https://ideone.com/eNmvng
I'm not sure what that syntaxis does with function visibility, but this works:
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1);
};
void func(const C& abc1)
{
cout << "in C's func" << endl;
}
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
::func(abc);
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}
Just for completeness sake, this works too:
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1)
{
cout << "in C's func" << endl;
}
};
// Make function visible in global scope
void func(const C& abc1);
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
::func(abc);
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}

Static Cast to CRTP Interface [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I am building up a CRTP interface and noticed some undefined behavior. So, I built up some sample code to narrow down the problem.
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a, int b, int c) : _a(a), _b(b), _c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10, 20, 30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
The output of this code is:
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
It appears that there is some problem when casting the child class, which implements the CRTP "interface", to the interface itself. This doesn't make sense to me because the class A plainly inherits from Base so, shouldn't I be able to cast an instance of A into Base?
Thanks!
You copy and slice when you cast to Base<T>.
Cast to a const Base<T>& instead:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
It turns out I was casting incorrectly to a value rather than a reference
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
should become
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;

Does std::any_cast call destructor? How the cast works?

#include <iostream>
#include <any>
using namespace std;
class c {
public:
c() :a{ 0 } { cout << "constructor\n"; }
c(int aa) :a{ aa } { cout << "Constructor\n"; }
~c() { cout << "destructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
}
destructor called after each any_cast.
and, below code makes run-time error.
I think the cause is any_cast(C)'s work pipeline is might be like
~C() then X(C) ERROR!!C doesn't exist
any_cast really work like that?
I add blow codes and make run-time error.
class X {
public:
X() :a{ 0 } { cout << "xonstructor\n"; }
X(c& aa) :a{ aa.get() } { cout << "Xonstructor\n"; }
~X() { cout << "Xdestructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<X>(a).get() << '\n';
//runtime error after '!'
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<X>(a).get() << '\n';
}
You are copying a c (or X) from the one within the std::any. That copy is destroyed at the end of the expression, after having been streamed out.
any_cast does not do any conversion. It throws if you ask it for a type different to the one it stores. When you have emplaced a c and asked for an X, it throws std::bad_any_cast, because X is not c.

about ctors and inheritance

Im kinda new to C++.
I have an assignment where I should implement c class' default ctor and cctor so that theyll print "c::ctor" and "c::cctor" respectively.
I have no idea of how to deal with this, help would be appreciated.
#include <iostream>
#include <string>
using namespace std;
class a {
public:
a(const char* sname)
: _sname(sname) {
cout << "a::ctor" << endl;
}
a(const a& s) { cout << "a::copy ctor" << endl; }
virtual ~a() { cout << "a::dtor " << endl; }
void f1() { cout << "a::f1()" << endl; f2(); }
virtual void f2() = 0;
private:
string _sname;
};
class b1 : virtual public a {
public:
b1(const char* saname, const char* ssname)
: _sname1(saname), a(ssname) {
}
b1(const b1& b1) : a(b1) { cout << "b1 :: copy ctor << endl"; }
~b1() { cout << "b1::dtor" << endl; }
virtual void f1() { cout << "b1::f1()" << endl; }
virtual void f2() { cout << "b1::f2()" << endl; }
virtual void f3() { cout << "b1::f3()" << endl; }
private:
string _sname1;
};
class b2 : virtual public a {
public:
b2(const char* saname, const char* ssname)
: _sname2(saname), a(ssname) {
cout << "b2::ctor" << endl;
}
b2(const b2& b2) : a(b2) { cout << "b2::copy ctor" << endl; }
~b2() { cout << "b2::dtor" << endl; }
virtual void f3() { f1(); cout << "b2::f3()" << endl; }
private:
string _sname2;
};
class c : public b1, public b2 {
public:
c();
c(const c& c);
~c() { cout << "c::dtor" << endl; }
virtual void f1() { a::f1(); cout << "c::f1()" << endl; }
void f3() { cout << "c::f3()" << endl; }
};
In case of virtual inheritance, things are more complicated for the constructors and destructors. The constructors and the destructors of the virtual base class a should also be called in the c class since the compiler cannot choose between b1 or b2 to build the (unique) a part in the c object. For the destructor, the compilers handles things to call the destructor of b1, the destructor of b2 and the destructor of a.
So you should implement
class c : public b1, public b2 {
public:
c() : b1("", ""), b2("", ""), a("") {}
c(const c& src) : b1(src), b2(src), a(src) {}
};
In general, you should try to avoid virtual inheritance when not necessary. But it is a good exercise to understand how it works.

Explicity pass base type

I have an explicit function that takes a reference to the base type of a class. What is the proper way to pass that in?
I am currently doing a static cast:
#include <iostream>
using namespace std;
struct Base
{
Base() { cout << "Base Constructor" << endl; }
Base(Base const& c) { cout << "Base-Base Constructor" << endl; }
};
struct Derived : public Base
{
Derived() { cout << "Derived Constructor" << endl; }
explicit Derived(Base const& c) { cout << "Derived-Base Constructor" << endl; }
Derived(Derived const& c) { cout << "Derived-Derived Constructor" << endl; }
};
int main()
{
Base B;
cout << "\n";
Derived D;
cout << "\n";
Base* test1 = new Derived(D);
cout << "\n";
Base* test3 = new Derived(static_cast<Base>(D));
cout << "\n";
Base* test2 = new Derived(B);
cout << "\n";
return 0;
}
but that calls the copy constructor of the base class.
I could pass *static_cast<Base*>(&D), but that seems a bit hackish. I feel like I am just overlooking a simple way to do this. Thanks.
Use this:
static_cast<Base&>(D)
Or this:
static_cast<const Base&>(D)