web-dev-qa-db-ja.com

「テスト*」から「テスト」に変換するための適切なコンストラクタがありません。コンストラクタ、

私はc++と私はコンストラクタとクラスで問題を抱えています。だから、これが私のヘッダーファイルです:

#pragma once
#include <string>
using namespace std;
class test
{

    private:
    string name;
    int number;

public:

    test();
    test(string i,int b);
};

これはcppファイルです:

#include "test.h"
#include <string>
using namespace std;


test::test(){}

test::test(string i,int b){
    this->name=i;
    this->number=b;
}

今、私が電話しようとすると

test t=new test("rrr",8);

私は得ます:

1   IntelliSense: no suitable constructor exists to convert from "test *" to "test" 

だから、クラスが*その名前に(たとえば、.cppファイルのないクラスにはアスタリスクがありませんが、他のすべてのクラスにはあります)?そして、私は何を間違っていますか?

12
klo

あなたはJava/C#のバックグラウンドから来ていると思います。 tはここでは参照型ではなく、値型です。 newは、オブジェクトへのポインタを返します。したがって、次のいずれかが必要です。

test t = test("rrr", 8);
test t("rrr", 8);
test *t = new test("rrr", 8);

ポインターにまだ慣れていない場合は、最後のポインターを使用しないでください。しかし、ポインタのセマンティクスを理解することはかなり重要です。教科書の関連する章を読むことをお勧めします...

26

したがって、名前に「*」が含まれるクラスの場合はどうなりますか(たとえば、.cppファイルのないクラスにはアスタリスクがありませんが、他のすべてのクラスにはあります)???

あなたは間違いなくポインタについて学ぶ必要があります。 _test *_とtestは、C++では2つの完全に異なる型です。これらのタイプの2つの変数を次に示します。

_test t;
test* p;
_

ここで、tのタイプはtestで、pのタイプは_test*_です。 _test*_を「testへのポインタ」と記述します。

多くの場合、ポインタはオブジェクトのメモリアドレスであると考えることができます。したがって、pにはポインタであるため、tのメモリアドレスを格納できます。これはtestです。オブジェクトのアドレスを取得するには、次のように単項_&_演算子を使用します。

_test t;
test* p = &t;
_

tistestオブジェクトであることに注意してください。 new test()と言う必要はありませんでした。ここで、C++は、C#やJavaなど、使用していた他の言語とは異なります。上記のC++コードでは、ttestオブジェクトです。

しかし、あなたはcannew test()でオブジェクトを作成するので、違いは何ですか?

_test t;_は、自動保存期間を持つtestオブジェクトを作成します。これは、スコープの最後で破棄されることを意味します(多くの場合、関数は内部で宣言されています)。

new test()は、動的な保存期間を持つtestオブジェクトを作成します。つまり、オブジェクトを手動で破棄する必要があります。そうしないと、メモリリークが発生します。この式はポインターを返すため、それを使用してポインターオブジェクトを初期化できます。

_test* p = new test();
_

それでは、問題を見てみましょう。

_test t=new test("rrr",8);
_

new test("rrr", 8)test(a _test*_)へのポインターを返すことがわかりました。ただし、それをtestオブジェクトに割り当てようとしています。あなたは単にこれを行うことはできません。 1つはアドレスで、もう1つはtestです。したがって、コンパイラーは、「_test *_からtestに変換するための適切なコンストラクターは存在しません」と言います。今では理にかなっていますね。

代わりに、自動保存期間を使用することをお勧めします。本当に必要な場合にのみ、newを使用してください。だからちょうどしてください:

_test t("rrr", 8);
_
5
test t=new test("rrr",8);

でなければなりません

//  v
test* t=new test("rrr",8);

それで、クラスに名前に「*」が含まれているものはどうですか

*はポインタを示すために使用されます。これはクラスの名前ではありません。しかし、それは大きなトピックなので、これについていくつかの研究を行う必要があります。

2
Kiril Kirov

*は名前の一部ではなく、オブジェクトがポインタであることを示す修飾子です。ポインタは、実際のオブジェクトが格納されているメモリ内の場所へのアドレスを保持する変数です。いくつかの基本:

int i = 5;
int * pI = &i;

int * pIは、intが保持されているメモリに配置するポインタを宣言することを意味します。 &iは、変数へのポインタを取得することを意味します。したがって、pIはメモリにアドレスを保持し、そこにiが格納されます。これでdereferenceポインタ-ポインタの値を取得できます:

int j = *pI;

次に、コンパイラーに、pIが指すアドレスに移動してその内容を取得するように指示します(pIはintへのポインターであるため、コンパイラーは、そこにintがあると想定します)。

さて、あなたの例に戻りましょう。 new演算子は、オブジェクトに動的にメモリを割り当てるため、次のようになります。

new test("rrr", 8);

その結果、テストクラスにメモリが割り当てられ、そのコンストラクタがパラメータ "rrr"と8で呼び出され、割り当てられたメモリへのポインタが返されます。これがtest変数に割り当てることができない理由です。この場合、new演算子はtest *を返します。

このコードを試してください:

test * t = new test("rrr", 8);
1
Spook

tをポインターとして定義していません:

test* t=new test("rrr",8);

あるいは単に

test t = test("rrr",8);
0
bash.d
T* t = new T;
//     ^^^

このオブジェクト構築でnewが使用されている場合、ポインターの作成を示します。動的にメモリを割り当てることは、あなたがそうするつもりでなかったと確信しています。むしろ、典型的なスタック割り当てオブジェクトの構築は、次のように簡単に行われます。

T t;

ポインタを作成してメモリを割り当てるつもりだったとしても、間違った方法で行いました。ポインタは*記号で作成されますが、これはコードにはありませんでした。次に、作成したメモリを使い終わったら、コードをdelete/delete[]することを忘れないでください。 delete[]は、動的に割り当てられた配列で使用されます。だから、これはあなたのポインターを探す方法です:

delete t;
0
0x499602D2