13.14 Converting constructors, explicit, and delete


https://www.learncpp.com/cpp-tutorial/converting-constructors-explicit-and-delete/
#include <cassert>
#include <iostream>

class Fraction
{
private:
	int m_numerator;
	int m_denominator;

public:
	// Default constructor
	Fraction(int numerator = 0, int denominator = 1)
		 : m_numerator(numerator), m_denominator(denominator)
	{
		assert(denominator != 0);
	}

	// Copy constructor
	Fraction(const Fraction& copy)
		: m_numerator(copy.m_numerator), m_denominator(copy.m_denominator)
	{
		// no need to check for a denominator of 0 here since copy must already be a valid Fraction
		std::cout << "Copy constructor called\n"; // just to prove it works
	}

	friend std::ostream& operator<<(std::ostream& out, const Fraction& f1);
	int getNumerator() { return m_numerator; }
	void setNumerator(int numerator) { m_numerator = numerator; }
};

void printFraction(const Fraction& f)
{
	std::cout << f;
}

std::ostream& operator<<(std::ostream& out, const Fraction& f1)
{
	out << f1.m_numerator << "/" << f1.m_denominator;
	return out;
}

int main()
{
	printFraction(6);

	return 0;
}
上のコードを実行すると、出力が思い通りになります
6/1
ただしprintFractionでは、Fractionタイプを受け入れるパラメータが必要です.
intタイプの6番をあげましたが、大丈夫です.もう失効しました.
Fractionのコンストラクション関数は単一の整数で初期化できるため,コンパイラは暗黙的にconvertを行った.
この暗黙的変換はすべてのタイプの初期化において共通である.
コンストラクション関数がこの暗黙的な変換を許可する場合:
変換構造関数と呼ぶ

The explicit keyword


この暗黙的な変換を許可したくない場合はexplicitキーワードを使用します.
#include <string>
#include <iostream>

class MyString
{
private:
	std::string m_string;
public:
	// explicit keyword makes this constructor ineligible for implicit conversions
	explicit MyString(int x) // allocate string of size x
	{
		m_string.resize(x);
	}

	MyString(const char* string) // allocate string to hold string value
	{
		m_string = string;
	}

	friend std::ostream& operator<<(std::ostream& out, const MyString& s);

};

std::ostream& operator<<(std::ostream& out, const MyString& s)
{
	out << s.m_string;
	return out;
}

void printString(const MyString& s)
{
	std::cout << s;
}

int main()
{
	MyString mine = 'x'; // compile error, since MyString(int) is now explicit and nothing will match this
	std::cout << mine;

	printString('x'); // compile error, since MyString(int) can't be used for implicit conversions

	return 0;
}
前述したように、明示的なキーワードを構造関数に使用すると、暗黙的な変換を防止できます.

The delete keyword


以前は明示的に暗黙的な変換を防止していました
今回はdeleteキーワードを使用して、パラメータとして特定のタイプを受け入れるコンストラクション関数を直接無効にすることができます.
#include <string>
#include <iostream>

class MyString
{
private:
	std::string m_string;

public:
	MyString(char) = delete; // any use of this constructor is an error

	// explicit keyword makes this constructor ineligible for implicit conversions
	explicit MyString(int x) // allocate string of size x /
	{
		m_string.resize(x);
	}

	MyString(const char* string) // allocate string to hold string value
	{
		m_string = string;
	}

	friend std::ostream& operator<<(std::ostream& out, const MyString& s);

};

std::ostream& operator<<(std::ostream& out, const MyString& s)
{
	out << s.m_string;
	return out;
}

int main()
{
	MyString mine('x'); // compile error, since MyString(char) is deleted
	std::cout << mine;
	return 0;
}
MyString(char)=delete;に設定されている場合
main関数のMystring mine(「x」);初期化しようとするとcompileエラーが発生します