Этот подход меняет только объект имени? - PullRequest
0 голосов
/ 16 ноября 2018

Я хочу поменять имя (то есть строку в cName []) двух кошек, используя подход указателя. Однако я хочу поменять только имя, а не объект. Я прав?

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string.h>
using namespace std;
class CAT
{
public:
    CAT(char * firstname) { strncpy(cName, firstname, 79); }
    ~CAT() { ; }
    char * getName() { return cName; }
    void setName(char *nameinput) { strncpy(cName, nameinput, 79); }
private:
    char cName[80];
};
void nameSwap(CAT *CatA, CAT *CatB)
{
    char testing[] = "testing";
    CAT temp =CAT(testing);
    temp = *CatA;
    *CatA = *CatB;
    *CatB = temp;
}
int main()
{
    char Taby[] = "Taby";
    char Felix[] = "Felix";
    CAT pA = CAT(Taby);
    CAT pB = CAT(Felix);
    cout << "The inital name pA is " << pA.getName() << " and pA is" << pB.getName() << endl;
    nameSwap(&pA, &pB);
    cout << "After approach" << endl;
    cout << "The name pA is " << pA.getName() << " and " << pB.getName() << endl;

    system("PAUSE");
    return 0;
}

1 Ответ

0 голосов
/ 16 ноября 2018

Вы на самом деле меняете все объекты, а не только имя CAT. Если вы хотите поменять только имя, вам нужно получить доступ к элементу cName аналогично тому, как вы это делаете для объектов. Вам также понадобится разрешение для доступа к члену cName в такой функции подкачки, которой у внешней функции не будет, поскольку cName является закрытой. Сделайте функцию подкачки членом вашего класса:

class CAT
{
public:
    CAT(const char* firstname) { strncpy(cName, firstname, 80); }
    ~CAT() {}
    const char* getName() const { return cName; }
    void setName(const char *nameinput) { strncpy(cName, nameinput, 80); }
    void swapName(CAT& CatB)
    {
        char tmp[80];
        strncpy(tmp, CatB.cName, 80);
        strncpy(CatB.cName, cName, 80);
        strncpy(cName, tmp, 80);
    }
private:
    char cName[80];
    // other CAT attributes won't be affected by the name swap
};

И назови это так

pA.swapName(pB); // or pB.swapName(pA); - same result

Но рассмотрите возможность использования std::string вместо char[]. Скоро вы обнаружите, что со строками C ++ гораздо проще работать, а также при их замене меняются только указатели на базовую память, поэтому она более эффективна.

std::string one;
std::string two;
one.swap(two);

Редактировать: В соответствии с запросом, я добавил версию, используя указатели. Я сделал это на скорую руку и не отладил его, поэтому я, вероятно, допустил много ошибок. Сначала я создал новый класс с именем wong_string, который будет содержать имя и любые другие атрибуты, пригодные для строк.

#include <stdexcept>
#include <cstring>

class wong_string {
    char* m_data;
    static char* duplicate(const char* str) {
        size_t len = std::strlen(str)+1;
        char* rv = new char[len];
        std::memcpy(rv, str, len);
        return rv;
    }
public:
    // default constructor: wong_string howdy1;
    wong_string() : m_data(nullptr) {}
    // conversion constructor: wong_string howdy2("value2");
    wong_string(const char* cstr) :
        m_data(duplicate(cstr))
    {}
    // copy constructor: wong_string howdy3 = howdy2;
    wong_string(const wong_string& rhs) : wong_string(rhs.m_data) {}
    // move constructor: wong_string howdy4 = wong_string("value4");
    wong_string(wong_string&& rhs) : m_data(rhs.m_data) {
        rhs.m_data = nullptr;
    }
    // copy assignment operator: (wong_string howdy5;) howdy5 = howdy4;
    wong_string& operator=(const wong_string& rhs) {
        if(this!=&rhs) {
            char* tmp = duplicate(rhs.m_data);
            if(m_data) delete []m_data;
            m_data = tmp;
        }
        return *this;
    }
    // copy assignment operator from c string
    wong_string& operator=(const char* rhs) {
        *this = wong_string(rhs);
        return *this;
    }
    // move assignment operator: (wong_string howdy6;) howdy6 = wong_string("value6");
    wong_string& operator=(wong_string&& rhs) {
        if(this!=&rhs) {
            m_data = rhs.m_data;
            rhs.m_data = nullptr;
        }
        return *this;
    }
    // destructor, free memory allocated by duplicate(), if any
    ~wong_string() {
        if(m_data) delete []m_data;
    }
    // comparisons
    bool operator==(const wong_string& rhs) const {
        return strcmp(m_data, rhs.m_data)==0;
    }
    bool operator!=(const wong_string& rhs) const {
        return !(*this==rhs);
    }
    // conversion to a normal c string
    operator char const* () const { return m_data; }
    // output stream operator
    friend std::ostream& operator<<(std::ostream&, const wong_string&);
    // input stream operator - not implemented yet
};

с этим, ваш CAT может быть превращен в что-то вроде этого:

class CAT
{
public:
    CAT(const char* firstname, const char* nickname=nullptr) :
        cName(firstname),
        cNickName(nickname?nickname:firstname)
    {}
    ~CAT() {}
    const char* getName() const { return cName; }
    void setName(const char *nameinput) { cName=nameinput; }
    void swapName(CAT& CatB)
    {
        std::swap(cName, CatB.cName);
    }
private:
    wong_string cName; // Madame Florence Jenkins III
    // other CAT attributes won't be affected by the name swap
    wong_string cNickName; // Ms. Miao
};

Итак, вот оно. Указатели в изобилии ...

...