Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Длина и сдвиг строки - Полиморфизм


Автор: ArniLand 22.4.2010, 19:38
Написал программу по полиморфизму и виртуальным функциям которая измеряет длину строки и сдвигает строку(чтобы первый символ стал последним). Но программа выдает не правильный результат. Помогите исправить пожалуйста, чтобы программа выводила правильный результат.

Результат:
http://piccy.info/view3/30805/7fdb7ee9cd485aced7140a75c70918e9/

Код программы:
Код

//Row.h
#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
class Row
{
public:
    virtual char LengthofRow() = 0;
    virtual int Right() = 0;
};

class Numeral : public Row
{
private:
    char *Str;

public:
    Numeral(char* pStr)
    {
        Str = pStr;
    }
    ~Numeral();
    

    virtual char LengthofRow()
    {
        int Length;
        Length = strlen(Str);
        return Length;
    }

    virtual int Right()
    {
        int len = LengthofRow();
        char temp = Str[len - 1];
        for (int i = len - 1; i > 0; i--)
        Str[i] = Str[i - 1];
        Str[0] = temp;
        cout << " Sdvig vpravo na odin simvol -" << Str;
        return 0;
    }
};

class SmallLetters : public Row
{
private:
    char *Str_1;
public:
    SmallLetters(char* pStr_1)
    {
        Str_1 = pStr_1;
    }
    ~SmallLetters();

    virtual char LengthofRow()
    {
        int Length_1;
        Length_1 = strlen(Str_1);
        return Length_1;
    }

    virtual int Right()
    {
        int len_1 = LengthofRow();
        char temp_1 = Str_1[len_1 - 1];
        for (int i = len_1 - 1; i > 0; i--)
        Str_1[i] = Str_1[i - 1];
        Str_1[0] = temp_1;
        cout << " Sdvig vpravo na odin simvol -" << Str_1;
        return 0;

    }
};
//main.cpp
#include "stdafx.h"
#include <string.h>
#include "Row.h"
#include <iostream>

using namespace std;

int main()
{
    char Num[40] = ("12345");
    char SmLet[45] = ("abcde");
    
    Numeral *objNum = new Numeral(Num);
    SmallLetters *objSm = new SmallLetters(SmLet);
    Row *obj[2] = {objNum, objSm};

    cout << "Dlina stroki " << obj[0]->LengthofRow()<<'\n';
    cout << "Sdvig " << obj[0]->Right()<<'\n';
    cout << "Dlina stroki " << obj[1]->LengthofRow()<<'\n';
    cout << "Sdvig " << obj[1]->Right()<<'\n';
    return 0;
}






    

Автор: toxx 22.4.2010, 20:25
при наследовании в производном классе не нужно объявлять её как виртуальную.

Автор: ArniLand 22.4.2010, 20:27
toxx, то есть просто убрать virtual в производных классах?

Добавлено через 4 минуты и 10 секунд
toxx, вот убрал я virtual  в методах производных классов, но результат выбивает такой же как выше на скриншоте

Код

#include "stdafx.h"
#include <string.h>
#include <iostream>
using namespace std;
class Row
{
public:
    virtual char LengthofRow() = 0;
    virtual int Right() = 0;
};

class Numeral : public Row
{
private:
    char *Str;

public:
    Numeral(char* pStr)
    {
        Str = pStr;
    }
    ~Numeral();
    

    char LengthofRow()
    {
        int Length;
        Length = strlen(Str);
        return Length;
    }

     int Right()
    {
        int len = LengthofRow();
        char temp = Str[len - 1];
        for (int i = len - 1; i > 0; i--)
        Str[i] = Str[i - 1];
        Str[0] = temp;
        cout << " Sdvig vpravo na odin simvol -" << Str;
        return 0;
    }
};

class SmallLetters : public Row
{
private:
    char *Str_1;
public:
    SmallLetters(char* pStr_1)
    {
        Str_1 = pStr_1;
    }
    ~SmallLetters();

     char LengthofRow()
    {
        int Length_1;
        Length_1 = strlen(Str_1);
        return Length_1;
    }

    int Right()
    {
        int len_1 = LengthofRow();
        char temp_1 = Str_1[len_1 - 1];
        for (int i = len_1 - 1; i > 0; i--)
        Str_1[i] = Str_1[i - 1];
        Str_1[0] = temp_1;
        cout << " Sdvig vpravo na odin simvol -" << Str_1;
        return 0;

    }
};


Автор: toxx 22.4.2010, 20:55
Ну еще нужно правильно написать конструкторы, они у вас точно не верные...
Код

 Numeral(char* pStr)
    {
        Str = pStr;
    }

Код

 SmallLetters(char* pStr_1)
    {
        Str_1 = pStr_1;
    }


Автор: ArniLand 22.4.2010, 20:55
подскажите пожалуйста, что я не так написал в конструкторах?

Автор: toxx 22.4.2010, 21:10
Например так, для другого сами по аналогии напишите
Код

SmallLetters(const char* const pStr_1)
{
        size_t len=strlen(pStr_1);
        len_m=len;
        Str_1=new char[len+1];
        for(size_t i=0;i<len;i++)
            Str_1[i]=pStr_1[i];
        Str_1[len]='\0';
}

Еще добавьте виртуальный метод 
Код

size_t size(){return len_m;}

И соответственно в приватную часть переменную длинны
Код

size_t len_m


И думаю всё заработает как нужно =)

Добавлено через 1 минуту и 32 секунды
Также если по хорошему делать добавьте еще конструкторы по ссылке, по умолчанию, и перегрузку оператора=.

Автор: azesmcar 23.4.2010, 09:52
Цитата(toxx @  22.4.2010,  20:25 Найти цитируемый пост)
при наследовании в производном классе не нужно объявлять её как виртуальную.

во первых не "не нужно" а "можно не писать", а во вторых это никак не влияет на работу программу.


ArniLand

выдели неработающую часть, мы люди ленивые, читать 100 строк кода никому не охота, помоги нам помочь тебе.

Автор: toxx 23.4.2010, 10:27
Цитата

во первых не "не нужно" а "можно не писать", а во вторых это никак не влияет на работу программу.

azesmcar

просто сколько видел в книгах в теме с полиморфизмом пишут такие примеры.
Код

class A
{
     virtual int t(int i)=0;
     ...
}
class B:public A
{
      int t(int i){...}
      ...
}
class C:public A
{
      int t(int i){...}
      ...
}

Автор: azesmcar 23.4.2010, 10:32
Цитата(toxx @  23.4.2010,  10:27 Найти цитируемый пост)
просто сколько видел в книгах в теме с полиморфизмом пишут такие примеры.

Да, потому что если функция в базовом классе объявлена как виртуальная, то функция наследника автоматически становится виртуальной
Цитата

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides97) Base::vf.

но это не значит, что если написать virtual программа перестанет работать, просто можно и не писать.

Автор: toxx 23.4.2010, 10:42
azesmcar
Да я понимаю о чем вы =)
но всё же как писать правильно? то что работает это конечно понятно, но есть наверно какие то правила? я думаю не надо писать лишнего или как... просто чтобы на будующее знать как советовать людям=)
Когда читал тему про виртуальные функции классы и все эти тонкости заглянул в Страуструпа, там он не объявлял виртуальными функции в производных классах(если в базовом функции чисто виртуальная).

Автор: azesmcar 23.4.2010, 10:46
toxx

Это вопрос стиля, я предпочитаю писать, так сразу видно в наследниках что функция виртуальная..не надо лезть в исходники родителя чтобы посмотреть.

Автор: toxx 23.4.2010, 10:55
azesmcar
хмм понятно, вы прям моё мнение изменили к этой теме.
а вот если по теме, я правильно забраковал конструкторы автора?(просто там тупо можно было типа изменить у функций, которые длину строки изменяют на int(char LengthofRow()), но мне я думаю правильнее сначала разбораться с конструкторами, так как такое создание очень плохое на мой взгляд и то что это будет работать не оправдание в данной ситуации)
просто никто не отвечает больше, а мне когда один отвечаю как-то прям неуютно.

Автор: djamshud 23.4.2010, 11:08
azesmcar, этот подход тоже не лишен недостатка. В наследнике можно создать новую виртуальную функцию (для будущих поколений) и разбирайся потом в наборе виртуальных функций, виртуальны они от самого корня или нет. Исходя из этих соображений никогда не использую "лишнее" virtual.

ЗЫ. Сорри за тавтологию.

Автор: azesmcar 23.4.2010, 12:32
Цитата(djamshud @  23.4.2010,  11:08 Найти цитируемый пост)
azesmcar, этот подход тоже не лишен недостатка. В наследнике можно создать новую виртуальную функцию (для будущих поколений) и разбирайся потом в наборе виртуальных функций, виртуальны они от самого корня или нет. Исходя из этих соображений никогда не использую "лишнее" virtual.

я и не говорил что он идеален smile я же говорю - вопрос стиля.

Цитата(toxx @  23.4.2010,  10:55 Найти цитируемый пост)
а вот если по теме, я правильно забраковал конструкторы автора?(просто там тупо можно было типа изменить у функций, которые длину строки изменяют на int(char LengthofRow()), но мне я думаю правильнее сначала разбораться с конструкторами, так как такое создание очень плохое на мой взгляд и то что это будет работать не оправдание в данной ситуации)

в смысле копирование? да, конечно..нo и тут есть вопросы
Код

SmallLetters(const char* const pStr_1)
{
        size_t len=strlen(pStr_1); // почему бы не присвоить сразу len_m?
        len_m=len;
        Str_1=new char[len+1];
        for(size_t i=0;i<len;i++) // strcpy?
            Str_1[i]=pStr_1[i];
        Str_1[len]='\0';
}

Автор: toxx 23.4.2010, 12:43
Цитата

в смысле копирование? да, конечно..нo и тут есть вопросы

Да спасибо(узнал о правильности совета), насчет замечаний я старался обойтись без сторонних функций =)

Автор: djamshud 23.4.2010, 12:57
>просто никто не отвечает больше, а мне когда один отвечаю как-то прям неуютно.

Воспитывайте уверенность в себе).

>я старался обойтись без сторонних функций =) 

Это стандартная функция, заменяющая ненужные и медленные три строчки кода.

Автор: toxx 23.4.2010, 13:05
djamshud
Цитата

Это стандартная функция, заменяющая ненужные и медленные три строчки кода. 

ну вот как тут можно воспитать её если как не напишу, так медленно =) как оценить скорость работы функции к слову?

Автор: azesmcar 23.4.2010, 13:09
Цитата(toxx @  23.4.2010,  13:05 Найти цитируемый пост)
как оценить скорость работы функции 

визуально, с помощью тестов.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)