

以下の過去質問において、仮想関数における仮引数を基底クラスで書く場合の警告回避方法を質問したのですが、それに関連して、仮想関数の基底クラスにおける、参照の返り値についての質問です。

**関連質問:**  
[C++ Visual Studio で C4100
警告を回避したい](https://ja.stackoverflow.com/questions/94276/c-visual-
studio-%E3%81%A7-c4100-%E8%AD%A6%E5%91%8A%E3%82%92%E5%9B%9E%E9%81%BF%E3%81%97%E3%81%9F%E3%81%84)

仮想関数の返り値を参照にしている場合、関数定義でconst
std::shared_ptr`<Hoge>&`を返さないといけないと思うのですが、virtual const std::shared_ptr&
Get(){return nullptr;}ではC4172警告がでるので、これを回避できる方法はないでしょうか。

C4172警告の回避のためだけに、Baseクラスにstd::shared_ptr`<Hoge>`メンバ変数をつくって、コンストラクタなどでnewしてBase::Get()で返すことは避けたいと考えています。

これらのプログラム構造にした条件ですが、簡略化して記述していますが、BaseクラスとDerived1クラスを分けて継承させ、hogehoge->base_ptr->Get()をすることはプログラム構造上必須と考えているためBase::Get()を仮想関数にしているのと、  
もしBase::Get()を純粋仮想関数にする場合は、Derived2::Get()overrideでも上記のようにconst
std::shared_ptr`<Hoge>&`の返り値のためにstd::shared_ptr`<Hoge>`メンバ変数を用意しないといけないのではないかと思ったので、Base::Get()を純粋仮想関数にはしていません。

よろしくお願いします。

#### 現状のコード

※プログラムの記述が間違っていたので修正しました。

[code]

            //返り値として使用するクラス
    
            class Hoge
            {
            public:
                int num = 100;
            };
    
            //返り値として使用したいstd::shared_ptr<Hoge>をnewする
    
            static std::shared_ptr<Hoge> hoge_ptr = std::shared_ptr<Hoge>(new Hoge());
    
            //仮想関数Get()を持つ基底クラス
    
            class Base
            {
            public:
                virtual const std::shared_ptr<Hoge>& Get()
                {
                    //問題の箇所
                    return nullptr;
                }
            };
    
            //Baseクラスを継承してBase::Get()をオーバーライドするクラス
    
            class Derived1 : public Base
            {
            public:
                const std::shared_ptr<Hoge>& Get()override
                {
                    //本来欲しい関数内容を記述
    
                    return hoge_ptr;
                }
            };
    
            //メンバ変数としてBase*を持つクラス
    
            class HogeHoge
            {
            public:
                Base* base_ptr = nullptr;
            };
    
            //HogeHogeインスタンスをnew
    
            static HogeHoge* hogehoge_ptr = new HogeHoge();
    
            //HogeHogeクラスのBase*メンバ変数にDerived1ポインタをnewして代入する
    
            hogehoge_ptr->base_ptr = new Derived1();
    
    
            //他にもBaseを継承するクラスがあるが、Get()はオーバーライドしない
    
            class Derived2 : public Base
            {};
    
            int i = hogehoge_ptr->base_ptr->Get()->num;
    
            //標準出力
            std::cout << i << std::endl;
    
[/code]


CC BY-SA 4.0
2023-06-23T18:45:12.600
95338
2023-06-27T15:45:03.630
2023-06-24T06:25:18.513
3060
57637
question
c++ visual-studio
C++ で仮想関数の返り値が参照である場合の、基底クラス定義の返り値をどう書くか


（クラス構造の是非は置いておいて）

* * *

## 前提

この関数が呼ばれる前に何らかのチェックによって呼ばれない（呼ばれたらバグな）状況を想定しています。  
# バグではないのに呼ばれるなら、クラス構造を見直した方が良いです。

* * *

## 案1

返すオブジェクトが存在しないのであれば、 ~~例外を投げるしか無いのでは~~ 例外を投げることができます。

[code]

    #include <stdexcept>
    
    //返り値として使用するクラス
    
    class Hoge {};
    
    //仮想関数func()を持つ基底クラス
    
    class Base
    {
    public:
        virtual Hoge &func()
        {
            //問題の箇所
            throw std::logic_error("not supported");
        }
    };
    
[/code]

* * *

## 案2

どうしても例外を使いたくない場合は、Hogeクラスを階層化する方法で対応できるかもしれません。

[code]

    //返り値として使用するクラス
    
    class NullHoge {};
    class Hoge : public NullHoge {};
    
    //仮想関数func()を持つ基底クラス
    
    class Base
    {
    public:
        virtual NullHoge &func()
        {
            //問題の箇所
            static NullHoge aNullHoge;
            return aNullHoge;
        }
    };
    
    class Derived1 : public Base
    {
    public:
        Hoge &func()override
        {
            //本来欲しい関数内容を記述
    
            //HogeHogeインスタンスのBase*メンバ変数にDerived1*を代入
    
            hogehoge_ptr->base_ptr = new Derived1();
    
            //func()の返り値としてHoge&を期待する
    
            return static_cast<Hoge&>(hogehoge_ptr->base_ptr->func());
        }
    };
    
[/code]

* * *

## 案3

`const std::shared_ptr<Hoge> &`を返すのなら、例外を投げる案1以外に、単に空の`static
std::shared_ptr<Hoge>`オブジェクトの参照を返すこともできます。

[code]

    class Base
    {
    public:
        virtual const std::shared_ptr<Hoge> &Get()
        {
            //問題の箇所
            static std::shared_ptr<Hoge> aNullHoge;
            return aNullHoge;
        }
    };
    
[/code]


CC BY-SA 4.0
2023-06-23T23:25:30.920
95340
2023-06-27T15:45:03.630
2023-06-27T15:45:03.630
7291
7291
95338
answer