質問編集履歴

3 コードを変更

tiitoi

tiitoi score 13723

2019/03/13 20:34  投稿

C++ - gcc でコンパイルすると、親クラスのメンバー変数を子クラスから参照できない問題について
## 環境
* C++11
* Visual Studio 2017
* gcc version 5.4.0
## 内容
下記のような親子関係があるテンプレートクラスを [Curiously Recurring Template Pattern](https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E5%A5%87%E5%A6%99%E3%81%AB%E5%86%8D%E5%B8%B0%E3%81%97%E3%81%9F%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3(Curiously_Recurring_Template_Pattern)) で作りました。
```cpp
#include <iostream>
// 親クラス
template <class Child, class SomeType>
struct Base
{
   void interface()
   {
       static_cast<Child *>(this)->implementation();
   }
   void set_value(SomeType value)  
   {  
       member_ = value;  
   }  
 
 public:
   SomeType member_ = 1;
   SomeType member_;
};
// 子クラス1
// 子クラス
template <class SomeType>
struct Derived : Base<Derived<SomeType>, SomeType>
{
   void implementation()
   {
       std::cout << member_ << std::endl;
   }
};
int main(int argc, char *argv[])
{
   Derived<int>().interface();
   Derived<int> obj;
   obj.set_value(1);
   obj.interface();
}
```
このコードは VC++ では問題なく通り、実行すると `1` とメンバ変数 `member_` の値が出力されます。
しかし、gcc でビルドすると以下のコンパイルエラーが発生します。
```output
error: ‘member_’ was not declared in this scope
        std::cout << member_ << std::endl;
                     ^
```
this ポインタから参照するように修正すると、gcc でもコンパイルが通ります。
```diff
- std::cout << member_ << std::endl;
+ std::cout << this->member_ << std::endl;
```
----
自分の理解では、public で継承しているので、親クラスでアクセス修飾子が protected である member_ には、子クラスからもアクセスできるはずとの認識ですが、なぜ変数が定義されていないとエラーになってしまうのでしょうか。
## 聞きたいこと
* gcc でコンパイルエラーとなる理由
* C++ の仕様としては「コンパイルが通る」または「コンパイルエラーとなる」のどちらが正しいのか
すみませんが、よろしくおねがいします。
  • C++

    5388 questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • GCC

    218 questions

    GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

  • Visual Studio

    2909 questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

2 d

tiitoi

tiitoi score 13723

2019/03/13 20:27  投稿

C++ - gcc でコンパイルすると、親クラスのメンバー変数を子クラスから参照できない問題について
## 環境
* C++11
* Visual Studio 2017
* gcc version 5.4.0
## 内容
下記のような親子関係があるテンプレートクラスを [Curiously Recurring Template Pattern](https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E5%A5%87%E5%A6%99%E3%81%AB%E5%86%8D%E5%B8%B0%E3%81%97%E3%81%9F%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3(Curiously_Recurring_Template_Pattern)) で作りました。
```cpp
#include <iostream>
// 親クラス
template <class Child, class SomeType>
struct Base
{
   void interface()
   {
       static_cast<Child *>(this)->implementation();
   }
 public:
   SomeType member_ = 1;
};
// 子クラス1
template <class SomeType>
struct Derived : Base<Derived<SomeType>, SomeType>
{
   void implementation()
   {
       std::cout << member_ << std::endl;
   }
};
int main(int argc, char *argv[])
{
   Derived<int>().interface();
}
```
このコードは VC++ では問題なく通り、実行すると `1` とメンバ変数 `member_` の値が出力されます。
しかし、gcc でビルドすると以下のコンパイルエラーが発生します。
```output
error: ‘member_’ was not declared in this scope
        std::cout << member_ << std::endl;
                     ^
```
this ポインタから参照するように修正すると、gcc でもコンパイルが通ります。
```diff
- std::cout << member_ << std::endl;
+ std::cout << this->member_ << std::endl;
```
----
自分の理解では、public で継承しているので、親クラスでアクセス修飾子が protected である member_ には、子クラスからもアクセスできるはずとの認識ですが、なぜ変数が定義されていないとエラーになってしまうのでしょうか。
## 聞きたいこと
* gcc でコンパイルエラーとなる理由
すみませんが、よろしくおねがいします。
  • C++

    5388 questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • GCC

    218 questions

    GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

  • Visual Studio

    2909 questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

1 タイトル

tiitoi

tiitoi score 13723

2019/03/13 20:25  投稿

C++11 - gcc でコンパイルすると、親クラスのメンバー変数を子クラスから参照できない問題について
C++ - gcc でコンパイルすると、親クラスのメンバー変数を子クラスから参照できない問題について
## 環境
* C++11
* Visual Studio 2017
* gcc version 5.4.0
## 内容
下記のような親子関係があるテンプレートクラスを [Curiously Recurring Template Pattern](https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E5%A5%87%E5%A6%99%E3%81%AB%E5%86%8D%E5%B8%B0%E3%81%97%E3%81%9F%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3(Curiously_Recurring_Template_Pattern)) で作りました。
```cpp
#include <iostream>
// 親クラス
template <class Child, class SomeType>
struct Base
{
void interface()
{
static_cast<Child *>(this)->implementation();
}
public:
SomeType member_ = 1;
};
// 子クラス1
template <class SomeType>
struct Derived : Base<Derived<SomeType>, SomeType>
{
void implementation()
{
std::cout << member_ << std::endl;
}
};
int main(int argc, char *argv[])
{
Derived<int>().interface();
}
```
このコードは VC++ では問題なく通り、実行すると `1` とメンバ変数 `member_` の値が出力されます。
しかし、gcc でビルドすると以下のコンパイルエラーが発生します。
```output
error: ‘member_’ was not declared in this scope
std::cout << member_ << std::endl;
^
```
this ポインタから参照するように修正すると、gcc でもコンパイルが通ります。
```diff
- std::cout << member_ << std::endl;
+ std::cout << this->member_ << std::endl;
```
----
自分の理解では、public で継承しているので、親クラスでアクセス修飾子が protected である member_ には、子クラスからもアクセスできるはずとの認識ですが、なぜ変数が定義されていないとエラーになってしまうのでしょうか。
## 聞きたいこと
* gcc でコンパイルエラーとなる理由
* C++ の仕様としてはどちらが正しいのか
すみませんが、よろしくおねがいします。
  • C++

    5388 questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • GCC

    218 questions

    GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

  • Visual Studio

    2909 questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る