アフィリエイト広告を利用しています

広告

posted by fanblog

2017年11月09日

《その111》 フレンド関数(p.502演習14-3)


フレンド関数

 演算の対象となる左オペランドが、非クラス型となる利用が想定される2項演算子関数は、クラスのメンバ関数ではなく、非メンバ関数として実現しなければならない。


 次のようなクラス C があるとします。

class C {
int a;
int b;
public:
C(int p = 0, int q = 0) : a(p), b(q) { }
int get_a() const { return a; }
int get_b() const { return b; }
};

 コンストラクタ C は int型の単一引数で呼び出せますから、変換コンストラクタも兼ねています。

 2項+演算子関数を非メンバ関数として実現すると、次のようになります。

C operator+(const C& x, const C& y) {
return C(x.get_a() + y.get_a(), x.get_b() + y.get_b());
}


 演算子関数を利用する演算は、次のようなものです。

C x(5, 3);
C y(2);

x = x + y; // ※1
y = 2 + x; // ※2


 左オペランドが演算子関数を呼び出すオブジェクトですから、
  ※1 では C型オブジェクト x が、
  ※2 では 変換コンストラクタによって 2 が int型から C型に変換された C型オブジェクトが、
それぞれ、演算子関数の呼出し元になります。


 ヘッダに置かれた非メンバ関数は外部結合を持ちますから、上記の2項+演算子関数が複数のソースファイルにインクルードされるような使い方をするとエラーになります。
そこで、

inline C operator+(const C& x, const C& y) {
return C(x.get_a() + y.get_a(), x.get_b() + y.get_b());
}

として内部結合を持たせるか、あるいは、クラス定義の中でフレンド関数として

friend C operator+(const C& x, const C& y) {
return C(x.a + y.a, x.b + y.b);
}

のように定義すべきです。クラス定義の中で定義したフレンド関数はインライン関数です。
また、フレンド関数は、クラスの非公開メンバにアクセスできるので、

x.get_a() を
x.a と記述することが可能になります。



新版明解C++入門編 p.502 演習14-3
 簡易的な文字列クラス String を作成せよ。以下のコードを参考にして、コンストラクタ・デストラクタ・各メンバ関数を、自分で設計すること。

class String {
int len; // 文字列の長さ
char* ptr; // 文字列の先頭文字へのポインタ
public:
String(const char*); // 変換コンストラクタ
String(const String&); // コピーコンストラクタ
~string(); // デストラクタ
int length(); // 長さを求める
// +, = などの演算子を定義せよ。
};


// String.h
#ifndef ___Class_String
#define ___Class_String

#include <iostream>

class String {
int len;
char* ptr;

public:
String(const char*);
String(const String&);

~String() { delete[] ptr; }

int length() { return len; }
String& operator=(const String& x);
char& operator[](int i);

friend std::ostream& operator<<(std::ostream& s, const String& x);
friend String operator+(const String& x, const String& y);
};

#endif


// String.cpp
#include "String.h"

String::String(const char* s) {
const char* tmp = s;
len = 0;
while (*tmp++)
len++;
ptr = new char[len + 1];
for (int i = 0; i <= len; i++)
ptr[i] = *(s + i);
}

String::String(const String& x) {
if (&x == this) {
len = 1;
ptr = new char[1];
ptr[0] = '\0';
} else {
len = x.len;
ptr = new char[len + 1];
for (int i = 0; i <= len; i++)
ptr[i] = x.ptr[i];
}
}

String& String::operator=(const String& x) {
if (&x != this) {
if (len != x.len) {
delete[] ptr;
len = x.len;
ptr = new char[len + 1];
}
for (int i = 0; i <= len; i++)
ptr[i] = x.ptr[i];
}
return *this;
}

char& String::operator[](int i) {
if (i < 0 || i >= len)
std::cout << "!添字エラー。終了します。\n", exit(1);
return ptr[i];
}


String operator+(const String& x, const String& y) {
String temp = temp;
temp.len = x.len + y.len;
delete[] temp.ptr;
temp.ptr = new char[x.len + y.len + 1];
for (int i = 0; i < x.len; i++)
temp.ptr[i] = x.ptr[i];
for (int i = 0; i <= y.len; i++)
temp.ptr[i + x.len] = y.ptr[i];
return temp;
}

std::ostream& operator<<(std::ostream& s, const String& x) {
return s << x.ptr;
}


// StringTest.cpp
#include <iostream>
#include "String.h"
using namespace std;

int main()
{
String s1 = "how old is ";
String s2 = s1;
String s3 = "she";
String s4 = "?";
s4 = s2 + s3 + s4;

cout << s4 << '\n';
s4[0] = 'H';
cout << s4 << '\n';

cout << s4.length() << '\n';

cout << "I am 100 years old. " + s4 << '\n';
}

c14_03.png


新版 明解C 入門編 (明解シリーズ)

新品価格
¥2,916から
(2017/8/30 21:02時点)









--
この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/6948145
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2018年08月 >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。