2013-08-29 19 views
5

Jestem nowy w C++ i ostatnio podjąłem studia nad programowaniem zorientowanym na obiekt. Chciałem napisać własny moduł liniowej algebry przetwarzający trójwymiarowe wektory i matryce 3x3. Próbowałem zdefiniować macierz jako klasę złożoną z trzech wektorów.Konstruowanie klasy przy użyciu innej klasy C++

class vector { 
    public: 
    double n1, n2, n3; 
    vector (double a, double b, double c) { 
     n1 = a; n2 = b; n3 = c; 
     } 
    }; 

class matrix { 
    public: 
     vector m1, m2, m3; 
     matrix (vector a, vector b, vector c) { 
       m1 = a; m2 = b; m3 = c; 
       } 
     }; 

Jestem jednak otrzymuję błąd kompilacji:

In constructor `matrix::matrix(vector, vector, vector)': 
no matching function for call to `vector::vector()' 

Domyślam się, że nie robi program, wie jak skonstruować macierz przy użyciu klasy wektor zdefiniowałem. Jednak nie rozumiem, dlaczego. Jeśli ktokolwiek mógłby wyjaśnić, byłbym bardzo wdzięczny.

+1

Użyj listy initializer zamiast przypisując je w ciele konstruktora. –

+0

możliwy duplikat [Czym jest ta dziwna składnia dwukropka w konstruktorze?] (Http://stackoverflow.com/questions/1711990/what-is-this-weird-colon-member-syntax-in-the-constructor) –

+2

możesz chcieć umieścić swoją klasę wektorową w przestrzeni nazw, aby zapobiec pomyłce z 'std :: vector'. Ponieważ kiedy czytałem twoją klasę macierzy, poważnie myślałem, że zamierzasz użyć 'std :: vector', ale nie w tym przypadku. – hetepeperfan

Odpowiedz

6

Trzeba zainicjować swoich członków m1,m2,m3 przez liście inicjatora członkiem:

matrix (const vector& a, const vector& b, const vector& c) 
: m1(a),m2(b),m3(c) 

pamiętać, że:

  • Formularz ten może być używany tylko z konstruktorów.
  • Musisz (przynajmniej w wersji przed C++ 11) użyć tego formularza, aby zainicjować element danych o niestatycznych stałych const.
  • Musisz użyć tego formularza, aby zainicjować element danych o numerze odniesienia.

również pamiętać, istnieje std::vector, może chcesz zmienić nazwę własnego wektora utratę nazywania konfliktu przepisów i lepiej zdać vector przez const odniesienia.

1

Jest potrzebna domyślnego konstruktora klasy wektorze, jeden bez parametrów:

class vector { 
    public: 
    double n1, n2, n3; 
    vector() { // <- this one 
    n1 = 0; n2 = -1; // sample initializing code 
    }; 
    vector (double a, double b, double c) { 
     n1 = a; n2 = b; n3 = c; 
     } 
    }; 
4

Oto dlaczego to będzie źle:

Budowa obiektu dzieje się w wielu etapach. W przypadku klasy macierzy najpierw trzeba skonstruować wszystkie obiekty członkowskie i tylko , a następnie wykonać treść konstruktora. Ważną rzeczą, o której należy pamiętać, jest to, że przed wprowadzeniem ciała konstruktora wszystkie obiekty należące do członka (w twoim przypadku: , m2 i m3) musiały zostać skonstruowane.

Problem polega na tym, że kompilator nie może samodzielnie zbudować elementów vector: Zna tylko jeden konstruktor dla vector, a do budowy wymagany jest trzy modele: double s, których nie ma. Możesz dostarczyć kompilatorowi te brakujące argumenty konstruktora dla vector używając składni listy inicjalizacyjnej, jak sugeruje odpowiedź Billza.

Działa to, ponieważ lista inicjalizacyjna jest wykonywana podczas fazy budowania członu, która ma miejsce przed fazą konstruktor-ciało.

Alternatywnie, zapewnij domyślny konstruktor dla vector, aby kompilator mógł automatycznie konstruować elementy macierzy bez dodatkowych informacji, jak sugeruje odpowiedź Zaca.

0

Powodem dlaczego wystąpił ten błąd, że:

  1. Twoja klasa wektor ma domyślnego konstruktora jak zdefiniowano jeden wyraźny konstruktor z parametrami.
  2. Element danych jednego obiektu zostanie zainicjowany podczas konstrukcji obiektu, ale przed wykonaniem kodu w konstruktorze.

Kiedy kompilator chce utworzyć obiektu matrycy, to musi najpierw budować/inicjuj M1/​​M2/m3 befor te kody "{m1 = a M2 oznacza B; m3 = C;}" konstruktora matrycy. Jednak klasa m1/m2/m3 nie ma domyślnego konstruktora do wywołania. Dlatego kompilator zgłasza "W konstruktorze matrix::matrix(vector, vector, vector)': no matching function for call to wektor :: wektor()" "

Rozwiązaniem jest zainicjowanie listy m1/m2/m3 poprzez inicjalizację członka. Działa to, ponieważ:

  1. Kompilator dostarczy "domyślny konstruktor kopii" (właściwie tylko bit-mądry egzemplarz dla twojego przypadku), gdy nie jest zdefiniowany.
  2. Ten "domyślny konstruktor kopii" może zostać wywołany poprzez listę inicjalizacji członków.
0

Albo z "zaleca C++ 11" sposób:

matrix (vector a, vector b, vector c) 
: m1(std::move(a)),m2(std::move(b)),m3(std::move(c)) { 
} 
Powiązane problemy