目次
はじめに
C++のクラスから生成したオブジェクトは、関数の引数として渡したり、関数の戻り値として返したりすることができます。構造体の場合と同様に、ここでもポインタを利用するのが、効率的で一般的な手法です。
オブジェクトそのものをコピーして渡す「値渡し」に比べ、オブジェクトのアドレスだけを渡す「ポインタ渡し」は、特にオブジェクトのサイズが大きい場合に、プログラムのパフォーマンスを向上させます。
この記事では、関数の引数と戻り値の両方で、オブジェクトをポインタとして扱うための基本的な方法を解説します。
オブジェクトをポインタとして扱うサンプルコード
このコードは、Product
クラスと、それを操作するProductManager
クラスを定義します。
ProductManager::displayProduct
:Product
オブジェクトへのポインタを引数として受け取り、その情報を表示します。ProductManager::createDefaultProduct
:Product
オブジェクトを作成し、そのオブジェクトへのポインタを戻り値として返します。
完成コード
#include <iostream>
#include <string>
using namespace std;
// 「商品」クラス
class Product {
public:
int id;
string name;
void showInfo() {
cout << "ID: " << id << ", 商品名: " << name << endl;
}
};
// 商品を管理するクラス
class ProductManager {
public:
// 1. オブジェクトへのポインタを「引数」として受け取るメンバ関数
void displayProduct(const Product* p);
// 2. オブジェクトへのポインタを「戻り値」として返すメンバ関数
Product* createDefaultProduct();
};
void ProductManager::displayProduct(const Product* p) {
cout << "--- 商品情報を表示します ---" << endl;
// アロー演算子(->)でメンバ関数を呼び出す
p->showInfo();
}
Product* ProductManager::createDefaultProduct() {
// 関数内で変数が消滅しないように、staticで宣言
static Product defaultItem;
defaultItem.id = 999;
defaultItem.name = "標準サンプル品";
// 作成したオブジェクトのアドレス(&)を返す
return &defaultItem;
}
int main() {
ProductManager manager;
Product* p_item; // ポインタを格納する変数を準備
// 戻り値としてポインタを受け取る
p_item = manager.createDefaultProduct();
// 引数としてポインタを渡す
manager.displayProduct(p_item);
return 0;
}
コードの解説
1. オブジェクトへのポインタを引数として渡す
void ProductManager::displayProduct(const Product* p)
const Product* p
:displayProduct
関数の引数p
が、「Product
型のオブジェクトを指すポインタ」であることを示しています。const
を付けることで、この関数内でオブジェクトの内容が変更されないことを保証しています。
manager.displayProduct(p_item);
main
関数では、createDefaultProduct
から受け取ったポインタp_item
を、そのままdisplayProduct
関数に渡しています。これにより、displayProduct
関数は、main
関数が指しているのと同じオブジェクトを操作できます。
2. オブジェクトへのポインタを戻り値として返す
Product* ProductManager::createDefaultProduct()
Product*
: 関数の戻り値の型が、「Product
型のオブジェクトを指すポインタ」であることを示しています。
static Product defaultItem;
- 関数内で定義されたローカル変数は、通常、関数が終了するとメモリから消えてしまいます。その消えた変数のアドレスを返しても無意味です。
static
キーワードを付けて変数を宣言することで、その変数はプログラムが終了するまでメモリ上に存在し続けるようになります。これにより、関数が終了した後でも、返されたポインタが有効なオブジェクトを指し示すことが保証されます。
return &defaultItem;
static
で宣言したdefaultItem
オブジェクトのメモリアドレスを、アドレス演算子&
で取得し、関数の戻り値として返しています。
まとめ
今回は、クラスのオブジェクトを、関数の引数や戻り値としてポインタで扱う方法を解説しました。
- 引数:
void Func(ClassName* p)
のようにポインタ型で受け取る。呼び出し側はFunc(&obj)
のようにアドレスを渡す。 - 戻り値:
ClassName* Func()
のようにポインタ型を返し、関数内ではstatic
で宣言したオブジェクトのアドレスをreturn &obj
のように返すのが一つの安全な方法。
オブジェクトをポインタでやり取りするこの手法は、C++プログラミングにおける基本であり、効率的なプログラムを書く上で必須のテクニックです。