运算符无理由地更改类的参数(* int)

时间:2011-11-26 12:18:48

标签: c++ class pointers operator-overloading arguments

在我的班级文件中,我已经:

class File
{
    std::vector<char> name, timeOfCreation, timeOfLastEdit, content;
    std::vector<char>::const_iterator* pPos, *pPosOfEnd;
    int *pSize;
    bool *pForcedSize;
    void setTimeOfLastEdit();
    int* indexOfLastChar, *indexOfCurrentChar;

    friend class Interface;
    friend class Directory;
public:
    File(std::string, int argSize = 0, std::string arg_content = 0); // constructor
    File(); // constructor
    File(const File&); // copy constructor
    ~File(); // destructor
    char* returnName(); 

    File& operator = (const File&);
    File operator += (const int);
    File operator -= (const int);
    File& operator ++ (); // prefix
    File& operator -- (); // prefix
    File operator ++ (int); // postfix
    File operator -- (int); // postfix

    bool operator ! ();

    int operator () (char*, int);

    friend  bool operator == (const File&, const File&);
    friend  bool operator != (const File&, const File&);
    friend  bool operator >= (const File&, const File&);
    friend  bool operator <= (const File&, const File&);
    friend  bool operator < (const File&, const File&);
    friend  bool operator > (const File&, const File&);

    friend std::istream & operator >> (std::istream&, File&);
    friend std::ostream & operator << (std::ostream&, File);

};

和我的operator()是这样的:

int File::operator () (char* contentNextNBytes, int n)
{
    int i; int j = 0;
    std::vector<char>::const_iterator it = content.begin();
    for(j = 0; j < *indexOfCurrentChar; j++)
        ++it;

    for(i = 0; i < n; i++)
    {
        contentNextNBytes[i] = *it;
        if(i == *indexOfLastChar-1) 
        {
            contentNextNBytes[i+1] = '\0';
            *indexOfCurrentChar = i+1;
            return i+1;
        }
        ++it;
    }

    contentNextNBytes[i] = '\0';
    *indexOfCurrentChar = n;
    return n;
}

在我的另一个类Interface中,我用int i = dir[index](buffer, n)调用operator(),其中n是字节数,index是目录中File的索引。

现在,正如在运算符中实现的那样,值* indexOfCurrentChar指向应该(并且确实)成为从File中提取的最后一个字符的位置。然而,当我再次使用int j = dir[index](buffer, n1)调用相同的运算符时,正好当程序进入运算符{}时,它会再次将* indexOfCurrentChar的值更改为0,而我的代码应该从最后一个char继续并读取文件

中的下一个n1个字节

为什么会这样? :(

这是我用来在类Interface中调用运算符的代码的一部分:

 buffer = new char[n+1];
    k = d[index](buffer, n);
    std::cout<<"Extracting of "<<k<<" bytes succeeded, and here is the content extracted:\n";
std::cout<<"\""<<buffer<<"\"";

Edit1:这是我改变indexOfCurrentChar的地方:

1)在赋值运算符=(但是,我没有在我的Interface类中调用它) 2)在复制构造函数中(也没有在Interface类中使用它,它只复制值) 3)在File构造函数中:

File::File()
{
    // stuff
    indexOfCurrentChar = new int;
} //I'm not setting its value, just allocating memory

4)在File构造函数中:

File::File(std::string arg_name, int arg_size, std::string arg_content)
{
     // stuff
     indexOfCurrentChar = new int;
     *indexOfCurrentChar = 0;
    //setting it to 0, but its just at creation time
}

5)在&gt;&gt;操作者 //获取文件内容

std::cout<<"Enter file content: ";
    *object.indexOfCurrentChar = 0;
    while( in.get(c) && c != '\n');
    i = 0;
    in.get(c);
    if(*(object.pSize) == 0)
    {
        while(c != '\n')
        {
            object.content.push_back(c);
            in.get(c);  
            ++i;
        }
        *(object.pSize) = (int)object.content.size();
        *(object.pPosOfEnd) = object.content.end();
        *object.indexOfLastChar = i;
    }
    else
    {
        i = 0;
        std::vector<char>::const_iterator it = object.content.begin();
        while(c != '\n')
        {
            if(i == *object.pSize)
            {
                *object.pPosOfEnd = it;
                *object.indexOfLastChar = i;
            }
            if(i >= *object.pSize)
            {
                in.get(c);
                continue;
            }
            object.content.push_back(c);
            in.get(c);
            ++i;
        }
    }


    *(object.pPos) = object.content.begin();

就是这样:))

Aaaaand虽然我很遗憾向全世界展示这个,但这是我丑陋的Interface类方法。我的所有程序输入/输出都是通过Interface.writeOutput方法管理的,它位于:

Interface::Interface()
{
    menu = new char*[12];
    menu[0] = "Welcome, please select an option from the following, by pressing the respective numbers:";
    menu[1] = "1  Create a Directory\n2  Create a single File\n3  Exit program";
    menu[2] = "Ok, now please select a further option:";
    menu[3] = "Enter the number of Files you want to import: ";
    menu[4] = "Enter the files...";
    menu[5] = "1  Write out the Directory details\n2  Extract N bytes from a desired file\n3  Remove a file with desired name from the Directory\n4  Write content of a file\n0  Go back to the beginning";
    menu[6] = "Enter the index of the file: ";
    menu[7] = "Enter how many bytes to extract: ";
    menu[8] = "Content of the extracted bytes: ";
    menu[9] = "Enter the name of the file: ";
    menu[10] = "What do you want to do next?";
    menu[11] = "Please enter a regular number...";
}


void Interface::writeMenu()
{
    Error e;
    char c, tmp[5], name[30];
    int n, k, index, i, numDir;
    char *buffer; 
    int *haveReadFiles;

    std::cout<<menu[0];
    std::cout<<"\n\n";
startMenu: 
    std::cout<<menu[1];
    std::cout<<"\n\n";
    std::cin>>c;
    if((!isdigit(c)) || ( c != '1' && c!= '2' && c!='3'))
    {
        std::cout<<"\n"<<menu[11]<<"\n\n";
        goto startMenu;
    }
    if(c == '1')
    {
        std::cout<<"Enter the name of the directory: ";
        std::cin>>name;
        Directory d(name);
        std::cout<<"\n\n\nEnter number of files of directory: ";
        std::cin>>numDir;
        haveReadFiles = new int[numDir];
        if(!haveReadFiles)
        {
            e.writeToOutput(7);
            exit(1);
        }

        for(i = 0; i < numDir; i++)
        {
        haveReadFiles[i] = 0;   
            //std::cin.ignore(5,'\n');
        //  std::cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
            File f;
            std::cin>>f;
            d += f;
        }

    menu1:
        std::cout<<"\n\n"<<menu[2]<<"\n\n";
menuRepeat:
        std::cout<<menu[5];
        std::cout<<"\n\n";
        std::cin>>c;
        if(!isdigit(c) || (c != '1' && c!= '2' && c!='3' && c != '4' && c != '0'))
        {
            std::cout<<"\n"<<menu[11];
            goto menu1;
        }
        switch(c)
        {
        case '0': goto startMenu;break;
        case '1': std::cout<<d;break;
        case '2': 
            {
                menu2:
                std::cout<<"\n\n"<<menu[6];

                std::cin>>tmp;
                for(i = 0; i < (int)strlen(tmp); i++)
                    if(!isdigit(tmp[i]))
                    {
                        std::cout<<"\n\n"<<menu[11];
                        goto menu2;
                    }
                index = atoi(tmp);
                menu3:
                std::cout<<"\n\n"<<menu[7];
                std::cin>>tmp;
                for(i = 0; i < (int)strlen(tmp); i++)
                    if(!isdigit(tmp[i]))
                    {
                        std::cout<<"\n\n"<<menu[11];
                        goto menu3;     
                    }
                n = atoi(tmp);


                buffer = new char[n+1];
                k = d[index](buffer, n);
                std::cout<<"Extracting of "<<k<<" bytes succeeded, and here is the content extracted:\n";
                std::cout<<"\""<<buffer<<"\"";
            } break;
        case '3':
            {
                std::cout<<"\n\nEnter the name of the file: ";
                std::cin>>name;
                d -= name;
                std::cout<<"...file removed!\n";
                std::cout<<"Directory without the removed file looks like this: \n\n"<<d;
            }break;
        case '4': 
            {
                menuFF:
                std::cout<<"\n\nEnter the index of the desired file: ";
                std::cin>>tmp;
                for(i = 0; i < (int)strlen(tmp); i++)
                    if(!isdigit(tmp[i]))
                    {
                        std::cout<<"\n\n"<<menu[11];
                        goto menuFF;
                    }
                index = atoi(tmp);
                std::cout<<"\nHere's the content:\n";
                File ff = d[index];
                std::vector<char>::const_iterator iter = ff.content.begin();
                for(; iter < ff.content.end(); ++iter)
                {
                    std::cout<<*iter;
                }
                std::cout<<"\n\n";
            }
        }
        menu4:
        std::cout<<"\n\nWhat do you want to do now?\n\n1  Exit program\n2  Go back to start menu\n3  Do more stuff with your Directory\n\n";
        std::cin>>c;
        if((!isdigit(c)) || ( c != '1' && c!= '2' && c!='3'))
        {
            std::cout<<"\n"<<menu[11];
            goto menu4;
        }
        if(c=='1')
        {
            "Thank you, goodbye...";
            exit(0);
        }
        if(c=='2')
            goto startMenu;
        if(c=='3')
            goto menuRepeat;
    }
    else if(c=='2')
    {
        std::cout<<"Enter your file...\n";
        File g;
        std::cin>>g;
        menuZZ:
        std::cout<<"\n\nHere's what you can do with your file: \n\n1  Extract N bytes of content from it\n2  Write its content out\n3  Write its properties out\n4  Return to start menu\n\n";
        std::cin>>c;
        switch(c)
        {
        case '1':
            {

                menuYY:
                std::cout<<"\n\n"<<menu[7];
                std::cin>>tmp;
                for(i = 0; i < (int)strlen(tmp); i++)
                    if(!isdigit(tmp[i]))
                    {
                        std::cout<<"\n\n"<<menu[11];
                        goto menuYY;        
                    }
                n = atoi(tmp);
                buffer = new char[n+1];
                k = g(buffer, n);
                std::cout<<"Extracting of "<<k<<" bytes succeeded, and here is the content extracted:\n";
                std::cout<<"\""<<buffer<<"\"";
                std::cout<<"\n\n";
                goto startMenu;
            } break;
        case'2':
            {
                std::vector<char>::const_iterator it = g.content.begin();
                for(; it < g.content.end(); ++it)
                {
                    std::cout<<*it;
                }
                std::cout<<"\n\n";
            }
        case'3':
            {
                std::cout<<g<<"\n\n";
                goto startMenu;
            } break;
        case'4': 
            {
                std::cout<<"\n\n";
                goto startMenu;
            } break;
        default:
            {
                std::cout<<menu[11];
                goto menuZZ;    
            }

        }
    }
    else
    {
        std::cout<<"Thank you, goodbye... ";
        exit(0);
    }
}

编辑2:

最后但并非最不重要的是Directory::operator [] implementation

标题:File& operator [] (int);

实施:

 File& Directory::operator [] (int index)
{
    std::vector<File>::const_iterator i = arr.begin();
    for(int j = 0; j < index; ++j)
        ++i;
    File* temp = new File;
    *temp = *i;
    return *temp;
    delete temp;
}

享受^^

3 个答案:

答案 0 :(得分:2)

我的猜测是问题在于Directory类以及它存储和返回File个对象的方式。例如,如果Directory::operator[]返回File而不是File &,那么对返回的对象所做的任何更改都不会保留到Directory的内部副本,所以连续两次打电话,如

int i = dir[index](buffer, n);
int j = dir[index](buffer, n1);

实际上导致在两个不同的临时File::operator()对象上调用File。这可以解释为什么*indexOfCurrentChar的值不是您所期望的。

修改

既然你已经展示了Directory::operator[]的实现,我可以自信地说我的怀疑是正确的。即使您更改了Directory::operator[]的签名以便它现在返回File &,您的实现仍然不会按照您希望的方式运行,因为它不会返回对正确{{1}的引用。 1}} object(File对象的内部副本)。三个陈述

Directory

创建File* temp = new File; *temp = *i; return *temp; 对象的内部Directory对象的新副本并返回对该对象的引用,因此对返回的File对象的成员变量所做的任何更改都不会反映在File向量的相应条目。由于Directory::arr会返回引用,因此将vector::operator[]的正文更改为

Directory::operator[]

应该给你想要的行为。

我可能还应该注意到,return arr[index]; 泄漏内存的当前实现:Directory::operator[]永远不会运行,因为delete temp;导致控件离开函数。

答案 1 :(得分:0)

我建议更换

 if(i == *indexOfLastChar-1)

 if(i == (*indexOfLastChar)-1)

我认为你正在读取'indexOf Last Char'之前的值并将其与i进行比较。

答案 2 :(得分:0)

我发布了这个作为评论,但我认为

indexOfCurrentChar = n; 

应该是

 *indexOfCurrentChar += n;