Strona 1 z 1

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 22 sie 2011, o 21:33
autor: diego_maradona
W Visual Studio express 2010 stworzyłem nowy projekt typu "CLR console aplication", a następnie dodałem dwa pozasystemowe nagłówki:

dispenserType.h

Kod: Zaznacz cały

//************************************************************
// Author: D.S. Malik
// 
// class dispenserType
// This class specifies the members to implement a dispenser.
//************************************************************
 

class dispenserType
{
public:
    int getNoOfItems() const; 
      //Function to show the number of items in the machine.
      //Postcondition: The value of numberOfItems is returned.

    int getCost() const; 
      //Function to show the cost of the item.
      //Postcondition: The value of cost is returned.

    void makeSale();  
      //Function to reduce the number of items by 1.
      //Postcondition: numberOfItems--;

    dispenserType(int setNoOfItems = 50, int setCost = 50); 
      //Constructor 
      //Sets the cost and number of items in the dispenser
      //to the values specified by the user.
      //Postcondition: numberOfItems = setNoOfItems;
      //               cost = setCost;
      //               If no value is specified for a 
      //               parameter, then its default value is 
      //               assigned to the corresponding member 
      //               variable.

private:
    int numberOfItems;     //variable to store the number of 
                           //items in the dispenser
    int cost;  //variable to store the cost of an item
};


int dispenserType::getNoOfItems() const
{
	return numberOfItems;
}

int dispenserType::getCost()
{
	return cost;
}

void dispenserType::makeSale()
{
	numberOfItems--;
}

dispenserType::dispenserType(int setNoOfItems, int setCost)
{
	if (setNoOfItems >= 0)
		numberOfItems = setNoOfItems;
	else
		numberOfItems = 50;

	if (setCost >= 0 )
		cost = setCost;
	else 
		cost = 50;
}
oraz

cashRegister.h

Kod: Zaznacz cały

// cash_register.h

class cashRegister
{
public:
	int getCurrentBalance() const;
	//Function to show the current amount in the cash register
	//Postcondition: The value of cashOnHand is returned 

	void acceptAmount(int amountIn);
	//Function to receive the amount deposited by 
	//the customer and update the amount in the register.
	//Postcondition: cashOnHand += amountIn;

	cashRegister(int cashIn = 500);
	//Constructor
	//Sets the cash in the register to a specific amount.
	//Postcondition: cashOnHand = cashIn;
	
private:
	int cashOnHand;

};

int cashRegister::getCurrentBalance() const
{
	return cashOnHand;
}

void cashRegister::acceptAmount(int amountIn)
{
	cashOnHand += amountIn;
}

cashRegister::cashRegister(int cashIn)
{
	if (cashIn >= 0)
		cashOnHand = cashIn;
	else 
		cashOnHand = 500;
}
plik z funkcją główną programu ma postać

Kod: Zaznacz cały

//*****************************************************
// Author: D.S. Malik
// 
// This program uses the classes cashRegister and 
// dispenserType to implement a candy machine.
// ****************************************************

#include "stdafx.h"
#include <iostream>
#include "cashRegister.h"
#include "dispenserType.h"
 
using namespace std;

void showSelection();
void sellProduct(dispenserType& product, 
                 cashRegister& pCounter);

int main()
{
    cashRegister counter;
    dispenserType candy(100, 50); 
    dispenserType chips(100, 65);
    dispenserType gum(75, 45);
    dispenserType cookies(100, 85);

    int choice;  //variable to hold the selection

    showSelection();
    cin >> choice;

    while (choice != 9)
    {
        switch (choice)
        {
        case 1: 
            sellProduct(candy, counter);
            break;
        case 2: 
            sellProduct(chips, counter);
            break;
        case 3: 
            sellProduct(gum, counter);
            break;
        case 4: 
            sellProduct(cookies, counter);
            break;
        default: 
            cout << "Invalid selection." << endl;
        }//end switch

        showSelection();
        cin >> choice;
    }//end while

    return 0;
}//end main

void showSelection()
{
    cout << "*** Welcome to Shelly's Candy Shop ***" << endl;
    cout << "To select an item, enter " << endl;
    cout << "1 for Candy" << endl;
    cout << "2 for Chips" << endl;
    cout << "3 for Gum" << endl;
    cout << "4 for Cookies" << endl;
    cout << "9 to exit" << endl;
}//end showSelection

void sellProduct(dispenserType& product, 
                 cashRegister& pCounter)
{
    int amount;  //variable to hold the amount entered
    int amount2; //variable to hold the extra amount needed

    if (product.getNoOfItems() > 0) //if the dispenser is not 
                                    //empty
    {
        cout << "Please deposit " << product.getCost()
             << " cents" << endl;
        cin >> amount;

        if (amount < product.getCost())
        {
            cout << "Please deposit another "
                 << product.getCost()- amount
                 << " cents" << endl;
            cin >> amount2;
            amount = amount + amount2;
       }

        if (amount >= product.getCost())
        {
            pCounter.acceptAmount(amount);
            product.makeSale();
            cout << "Collect your item at the bottom and "
                 << "enjoy." << endl;
        }
        else
            cout << "The amount is not enough. " 
                 << "Collect what you deposited." << endl;

        cout << "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
             << endl << endl;
    }
    else
        cout << "Sorry, this item is sold out." << endl;
}//end sellProduct
po skompilowaniu pojawia się error
1>candy_machine.obj : error LNK2028: unresolved token (0A000348) "public: void __thiscall dispenserType::makeSale(void)" (?makeSale@dispenserType@@$$FQAEXXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
Mógłby ktoś wytłumaczyć skąd on się bierze / co on oznacza?

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 22 sie 2011, o 21:58
autor: Afish
W funkcji sellProduct jest wywoływana funkcja makeSale, ale linker nigdzie nie może znaleźć jej kodu.

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 15:23
autor: diego_maradona
To co zrobić aby linker mógł znaleźć jej kod? stworzyć jakiś nowy plik, w którym są zawarte definicje funkcji?

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 15:46
autor: Afish
Sprawdź dwa razy ustawienia ścieżek, a jak to nie pomoże, to załóż nowy projekt. U mnie wszystko działa. Upewnij się, że dobrze includujesz plik - nad kodem napisałeś, że plik nazywa się cash_register.h, a dołączasz cashRegister.h. Poza tym dziwne jest, że kompilator nie wskazał Ci błędu w pliku dispenserType.h - w deklaracji funkcja getCost jest oznaczona jako const, a w definicji już tego nie ma. No i tak swoją drogą, w nagłówkach zwykło umieszczać się jedynie deklaracje, definicje umieszcza się w plikach cpp (wyjątkiem są szablony, ale to temat na inną bajkę). Do tego w nagłówkach powinieneś umieścić strażników (albo zrobionych na definach, albo na pragma once).

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 19:03
autor: diego_maradona
Program nie jest mój- definicje funkcji przepisywałem z książki, a resztę ściągnąłem i skopiowałem ze strony internetowej. Po dodaniu const nic się nie zmieniło, dalej wyskakuje ten sam błąd, biblioteki są wykrywane przez program bo jak zapisałem je w innym pliku to występował inny błąd mówiący o tym że nie da się ich wykryć. Definicje funkcji przeniosłem do plików dispenserType.cpp oraz cashRegister.cpp. Dalej bez zmian.

PS. mam zwyczaj zwracać uwagę tylko na pierwszy error w outpucie debbugera , ten nieszczęsny output w pełnej okazałości wygląda tak:
1>------ Build started: Project: candy_machine, Configuration: Debug Win32 ------
1> candy_machine.cpp
1>candy_machine.obj : error LNK2028: unresolved token (0A000348) "public: void __thiscall dispenserType::makeSale(void)" (?makeSale@dispenserType@@$$FQAEXXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2028: unresolved token (0A000349) "public: int __thiscall dispenserType::getCost(void)const " (?getCost@dispenserType@@$$FQBEHXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2028: unresolved token (0A00034A) "public: int __thiscall dispenserType::getNoOfItems(void)const " (?getNoOfItems@dispenserType@@$$FQBEHXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2028: unresolved token (0A00034D) "public: __thiscall dispenserType::dispenserType(int,int)" (??0dispenserType@@$$FQAE@HH@Z) referenced in function "int __cdecl main(void)" (?main@@$$HYAHXZ)
1>candy_machine.obj : error LNK2019: unresolved external symbol "public: void __thiscall dispenserType::makeSale(void)" (?makeSale@dispenserType@@$$FQAEXXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2019: unresolved external symbol "public: int __thiscall dispenserType::getCost(void)const " (?getCost@dispenserType@@$$FQBEHXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2019: unresolved external symbol "public: int __thiscall dispenserType::getNoOfItems(void)const " (?getNoOfItems@dispenserType@@$$FQBEHXZ) referenced in function "void __cdecl sellProduct(class dispenserType &,class cashRegister &)" (?sellProduct@@$$FYAXAAVdispenserType@@AAVcashRegister@@@Z)
1>candy_machine.obj : error LNK2019: unresolved external symbol "public: __thiscall dispenserType::dispenserType(int,int)" (??0dispenserType@@$$FQAE@HH@Z) referenced in function "int __cdecl main(void)" (?main@@$$HYAHXZ)
1>C:UsersTomekdocumentsvisual studio 2010Projectscandy_machineDebugcandy_machine.exe : fatal error LNK1120: 8 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
-- 23 sie 2011, o 19:14 --

PS. Okienko projektu po otwarciu:

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 20:32
autor: wszamol
Chyba źle tworzysz te pliki w swoim projekcie, u mnie również kod się kompiluje (po uwzględnieniu wskazówek Afisha). Oto zrzut ekranu, może to CI podpowie jak tworzyć nowe klasy
(Add->Class...)

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 23:14
autor: Afish
No to z taką liczbą błędów wszystko jest bardziej zrozumiałe. Linker nie widzi pliku dispenserType.h. I nie jest to nic dziwnego, bo powinieneś ten plik dodać do "Header Files". Dziwne jest jedynie to, że kompilator nie ma z tym plikiem problemów. Najlepiej załóż projekt od nowa, porządnie dodaj pliki i ma śmigać.

[C++] [Visual Studio 2010] załączanie własnych nagłówków

: 23 sie 2011, o 23:55
autor: diego_maradona
Po prostu chciałem dodać biblioteki i pliki .cpp z definicjami funkcji w klasach za pomocą ctrl+n, co w rzeczywistości było stworzeniem tych plików bez zaprzęgania ich do projektu . Użyłem ctrl+shift+a i teraz jest super