Giriş
Constructor Tipleri yazısında C++ ile kullanılabilecek diğer constructor'lar var
1. explicit constructor - C++11'den önce
Derleyicinin bir nesneyi yaratmak için kendi kendine verilen parametrenin tipini değiştirmesi engellemek demek.
Örnek
Foo sınıfı şöyle tanımlanmış olsun
Tek parametreli constructor'lar için explicit yazmak yetersiz. Brace Initialization yüzünden çok parametreli metodlara da explicit yazmak gerekir.
Örnek
Şöyle yaparız.
Böylece dizi olarak şöyle yapamayız.
Böylece metod çağrılarında şunu yapamayız.
Bence explicit tek parametreli constructor'larda her zaman kullanılmalı.
Örnek
Elimizde şöyle bir sınıf olsun.
4. Explicit Kullanırken Bazı Tipleri Kabul Etmemek
Örnek
Elimizde şöyle bir kod olsun.
Derleyicinin bir nesneyi yaratmak için kendi kendine verilen parametrenin tipini değiştirmesi engellemek demek.
Örnek
Foo sınıfı şöyle tanımlanmış olsun
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo (int foo)
{...}
...
};
DoBar isimli ve Foo alan bir metodumuz olsun.void DoBar (Foo foo)
{
...
}
DoBar şöyle çağrılabilir.int main ()
{
DoBar (42);
}
Ayrıca Foo şöyle yaratılabilir.int main() {
Foo f = 2;
}
Eğer constructor içinde explicit kelimesini kullanırsak Foo şöyle yaratılmak zorunda kalınır.Foo f (2);
2. explicit constructor - C++11'den sonraTek parametreli constructor'lar için explicit yazmak yetersiz. Brace Initialization yüzünden çok parametreli metodlara da explicit yazmak gerekir.
Örnek
Şöyle yaparız.
struct Bar { explicit Bar(int, int); };
Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY
ÖrnekBöylece dizi olarak şöyle yapamayız.
struct A {
explicit A( int b, int c ) {}
};
struct B {
B( int b, int c ) {}
};
int main() {
B b[] = {{1,2}, {3,5}}; // OK
A a1[] = {A{1,2}, A{3,4}}; // OK
A a2[] = {{1,2}, {3,4}}; // Error
return 0;
}
ÖrnekBöylece metod çağrılarında şunu yapamayız.
void bar(const Bar&) {}
bar({ 42, 42}); // invalid
3. explicit kullanmazsakBence explicit tek parametreli constructor'larda her zaman kullanılmalı.
Örnek
Elimizde şöyle bir sınıf olsun.
#include<iostream>
using namespace std;
class MyClass
{
string figName;
public:
MyClass(const string& s)
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
ostream& operator<<(ostream& ps, const MyClass& f)
{
os << f.getName();
return os;
}
int main()
{
MyClass f1("Hello");
cout << f1;
}
Bu kod stackoverflow exception fırlatır. Açıklaması şöyleWith MS VC++ compiler error happens because if you do not #include <string> you won't have operator<< defined for std::string.
When compiler tries to compile os << f.getName(); it looks for operator<< defined for std::string. Since it was not defined, compiler looks for alternatives. There is operator<< defined for MyClass and compiler tries to use it, and to use it it has to convert std::string to MyClass and this is exactly what happens because MyClass has non-explicit constructor! So, compiler ends up creating new instance of your MyClass and tries to stream it again to your output stream. This results in endless recursion:
4. Explicit Kullanırken Bazı Tipleri Kabul Etmemek
Örnek
Elimizde şöyle bir kod olsun.
class A
{
public:
explicit A(int a)
{
num = a;
}
int num;
};
Normalde int kullanmak gerekirken double ile de nesneyi ilklendirebiliyoruz. Şöyle yaparızint main()
{
A a1 = A(10.0);
std::cout << a1.num;
return 0;
}
Sadece int tipine izin vermek için şöyle yaparız.struct A
{
explicit A(int a)
: num(a)
{}
template<class T>
A(T) = delete;
int num;
};
int main()
{
//A a1=A(10.0); // error: use of deleted function 'A::A(T) [with T = double]'
A a2 = A(10); // OK
}
Explicit Constructor Kullanılmadığında Uyarı VermekÖrnek
Sınıfın implicit conversion yapan constructor kodu olsun. Yani şöyle olsun
class Duration
{
int seconds;
public:
Duration(int t_seconds) : seconds(t_seconds) { }
};
int main()
{
Duration t(30);
t = 60;
}
Bir zaman sonra explicit constructor yazalım. Eski kod derlensin ancak uyarı versin istersek şöyle yaparız
#include<concepts>
class Duration {
int seconds;
public:
template<std::same_as<int> T>
[[deprecated("uses implicit conversion")]]
Duration(T t_seconds) : Duration(t_seconds) { }
explicit Duration(int t_seconds) : seconds(t_seconds) { }
};
Açıklaması şöyleIf you want to allow t = 0.6, just change the std:same_as to std::convertible_to
yazı için teşekkürler :)
YanıtlaSilRica ederim. Faydalı olduysa ne mutlu :)
Sil