Наряду с попыткой всего, что предлагает Teo Chuen Wei Bryan, убедитесь, что вы также ссылаетесь на правильное имя Server / Instance в строке подключения.
Если вы используете краткую форму имени хоста / экземпляра на сервере базы данных или в файле web.config, убедитесь, что вы используете полное доменное имя (FQDN) / экземпляр
Кроме того, чтобы проверить подключение с сервера, на котором нет клиента SQL-сервера,
-> создать текстовый файл и изменить его расширение файла на .udl
-> Щелкните правой кнопкой мыши файл, и вы увидите вкладку подключения.
-> Введите имя сервера и зарегистрируйте информацию для проверки соединения с сервером базы данных.
Надеюсь, это поможет.
Хорошо, я попробую после чтения многих сообщений, объясняющих разбиение объектов, но не так, как это становится проблематичным.
Порочный сценарий, который может привести к повреждению памяти, следующий:
«Slicing» - это то, где вы назначаете объект производного класса экземпляру базового класса, тем самым теряя часть информации - часть его «нарезана».
Например,
class A {
int foo;
};
class B : public A {
int bar;
};
Таким образом, объект типа B
имеет два элемента данных: foo
и bar
.
Тогда, если вы должны были написать это:
B b;
A a = b;
Затем информация в b
о члене bar
теряется в a
.
A a = b;
a
теперь является объектом типа A
, который имеет копию B::foo
. Будет ошибкой вернуть его сейчас, я думаю.
– user
12 August 2011 в 13:27
B b1; B b2; A& b2_ref = b2; b2 = b1
. Вы могли бы подумать, что скопировали b1
в b2
, но вы этого не сделали! Вы скопировали часть i> из b1
в b2
(часть b1
, которая B
унаследована от A
), и оставила остальные части b2
без изменений. b2
теперь является франкенштейновским существом, состоящим из нескольких бит b1
, за которым следуют некоторые фрагменты b2
. Тьфу! Downvoting, потому что я думаю, что ответ очень промахивается.
– fgp
22 January 2013 в 16:07
B b1; B b2; A& b2_ref = b2; b2_ref = b1
& quot; Реальная проблема возникает, если вы i> & quot; ... вытекает из класса с не виртуальным оператором присваивания. Действительно ли A
предназначен для деривации? Он не имеет виртуальных функций. Если вы проистекаете из типа, вам приходится иметь дело с тем, что его функции-члены могут быть вызваны!
– curiousguy
29 June 2013 в 15:54
Все это хорошие ответы. Я хотел бы добавить пример выполнения при передаче объектов по значению vs по ссылке:
#include <iostream>
using namespace std;
// Base class
class A {
public:
A() {}
A(const A& a) {
cout << "'A' copy constructor" << endl;
}
virtual void run() const { cout << "I am an 'A'" << endl; }
};
// Derived class
class B: public A {
public:
B():A() {}
B(const B& a):A(a) {
cout << "'B' copy constructor" << endl;
}
virtual void run() const { cout << "I am a 'B'" << endl; }
};
void g(const A & a) {
a.run();
}
void h(const A a) {
a.run();
}
int main() {
cout << "Call by reference" << endl;
g(B());
cout << endl << "Call by copy" << endl;
h(B());
}
Выход:
Call by reference
I am a 'B'
Call by copy
'A' copy constructor
I am an 'A'
Когда объекту класса Derived присвоен объект Base class Object, все члены объекта производного класса копируются в объект базового класса, за исключением членов, которых нет в базовом классе. Эти члены удаляются компилятором. Это называется Object Slicing.
Вот пример:
#include<bits/stdc++.h>
using namespace std;
class Base
{
public:
int a;
int b;
int c;
Base()
{
a=10;
b=20;
c=30;
}
};
class Derived : public Base
{
public:
int d;
int e;
Derived()
{
d=40;
e=50;
}
};
int main()
{
Derived d;
cout<<d.a<<"\n";
cout<<d.b<<"\n";
cout<<d.c<<"\n";
cout<<d.d<<"\n";
cout<<d.e<<"\n";
Base b = d;
cout<<b.a<<"\n";
cout<<b.b<<"\n";
cout<<b.c<<"\n";
cout<<b.d<<"\n";
cout<<b.e<<"\n";
return 0;
}
Он будет генерировать:
[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'
Если D - производный класс базового класса B, то вы можете назначить объект типа Derived переменной (или параметру) типа Base.
ПРИМЕР
class Pet
{
public:
string name;
};
class Dog : public Pet
{
public:
string breed;
};
int main()
{
Dog dog;
Pet pet;
dog.name = "Tommy";
dog.breed = "Kangal Dog";
pet = dog;
cout << pet.breed; //ERROR
Хотя указанное назначение разрешено, значение, присвоенное переменной pet, теряет поле породы. Это называется проблемой нарезки.
2. КАК ИЗМЕНИТЬ ПРОБЛЕМУ СЦЕПЛЕНИЯ
Чтобы устранить проблему, мы используем указатели на динамические переменные.
ПРИМЕР
Pet *ptrP;
Dog *ptrD;
ptrD = new Dog;
ptrD->name = "Tommy";
ptrD->breed = "Kangal Dog";
ptrP = ptrD;
cout << ((Dog *)ptrP)->breed;
В этом случае ни один из элементов данных или функций-членов динамической переменной, на которые указывает ptrD (объект класса потомка), будет потерян. Кроме того, если вам нужно использовать функции, функция должна быть виртуальной.
dog
, которое не является частью класса Pet
(элемент данных breed
), не копируется в переменной pet
? Код интересуется только членами данных Pet
- видимо. Нарезка - определенно «проблема». если это нежелательно, но я не вижу этого здесь.
– curiousguy
18 February 2012 в 06:18
((Dog *)ptrP)
& Quot; Я предлагаю использовать static_cast<Dog*>(ptrP)
– curiousguy
18 February 2012 в 06:20
Проблема среза в C ++ возникает из семантики значений ее объектов, которая оставалась в основном из-за совместимости с C-структурами. Вам нужно использовать явный синтаксис ссылок или указателей для достижения «нормального» поведения объекта, обнаруженного на большинстве других языков, которые выполняют объекты, т. Е. Объекты всегда передаются по ссылке.
Короткими ответами являются то, что вы нарезаете объект путем присвоения производного объекта базовому объекту значением , то есть оставшийся объект является лишь частью производного объекта. Чтобы сохранить семантику стоимости, нарезка является разумным поведением и имеет относительно редкое применение, которое не существует на большинстве других языков. Некоторые люди считают это особенностью C ++, в то время как многие считают ее одной из особенностей / недостатков C ++.
struct
, совместимостью или другим не-смыслом, о котором вам говорил любой случайный священник ООП.
– curiousguy
27 November 2011 в 13:27
В C ++ объект производного класса может быть назначен объекту базового класса, но другой способ невозможен.
class Base { int x, y; };
class Derived : public Base { int z, w; };
int main()
{
Derived d;
Base b = d; // Object Slicing, z and w of d are sliced off
}
Обрезка объектов происходит, когда объект производного класса присваивается базе объект класса, дополнительные атрибуты объекта производного класса вырезаются для формирования объекта базового класса.
Я просто столкнулся с проблемой нарезки и тут же приземлился. Итак, позвольте мне добавить мои два цента к этому.
Приведем пример из «производственного кода» (или что-то вроде близкого):
Допустим, у нас есть то, что рассылает действия. Например, пользовательский интерфейс центра управления. Этот пользовательский интерфейс должен получить список вещей, которые в настоящее время могут быть отправлены. Поэтому мы определяем класс, содержащий информацию о доставке. Назовем это Action
. Таким образом, Action
имеет некоторые переменные-члены. Для простоты мы имеем только 2, являющиеся std::string name
и a std::function<void()> f
. Затем он имеет void activate()
, который просто выполняет член f
.
Таким образом, пользовательский интерфейс получает std::vector<Action>
. Представьте себе некоторые функции, такие как:
void push_back(Action toAdd);
Теперь мы установили, как это выглядит с точки зрения пользовательского интерфейса. Пока нет проблем. Но какой-то другой парень, который работает над этим проектом, внезапно решает, что существуют специальные действия, требующие дополнительной информации в объекте Action
. По какой причине. Это также можно решить с помощью лямбда-захватов. Этот пример не принимается 1-1 из кода.
Итак, парень происходит от Action
, чтобы добавить свой собственный вкус. Он передает экземпляр своего урожая в класс push_back
, но затем программа переходит в haywire.
Итак, что случилось? Как вы могли предположить : объект был отрезан.
Дополнительная информация из экземпляра потеряна, а f
теперь подвержен неопределенному поведению.
Надеюсь, что в этом примере рассказывается о тех людях, которые не могут себе представить, когда говорят о A
s и B
в какой-то мере.
Мне кажется, что нарезка - это не столько проблема, которая отличается от того, когда ваши собственные классы и программы плохо архивируются / разработаны.
Если я передаю объект подкласса в качестве параметра для метод, который принимает параметр суперкласса типа, я должен, конечно, знать об этом и знать внутренне, вызываемый метод будет работать только с объектом суперкласса (aka baseclass).
Мне кажется, необоснованное ожидание того, что предоставление подкласса, где запрашивается базовый класс, каким-то образом приведет к конкретным результатам подкласса, вызовет проблему разрезания. Его либо плохой дизайн при использовании метода, либо недостаточная реализация подкласса. Я предполагаю, что это обычно результат жертвовать хорошим дизайном ООП в пользу целесообразности или повышения производительности.
Найти похожие ответы здесь: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Нарезка означает, что данные, добавленные подклассом, отбрасываются, когда объект подкласса передается или возвращается по значению или из функции, ожидающей объект базового класса.
Объяснение: Рассмотрим следующее объявление класса:
class baseclass
{
...
baseclass & operator =(const baseclass&);
baseclass(const baseclass&);
}
void function( )
{
baseclass obj1=m;
obj1=m;
}
Поскольку функции копирования в базовом классе ничего не знают о производной, только копируется только базовая часть производного. Это обычно называют срезанием.
Большинство ответов здесь не могут объяснить, какова фактическая проблема с разрезанием. Они объясняют только доброкачественные случаи нарезки, а не предательские. Предположим, как и другие ответы, что вы имеете дело с двумя классами A
и B
, где B
получает (публично) из A
.
В этой ситуации C ++ позволяет вам передать экземпляр оператора B
в A
, а также в конструктор копирования. Это работает, потому что экземпляр B
может быть преобразован в const A&
, а именно, какие операторы присваивания и конструкторы-копии ожидают, что их аргументы будут.
B b;
A a = b;
Ничего плохого в этом нет - вы попросили экземпляр A
, который является копией B
, и это именно то, что вы получаете. Конечно, a
не будет содержать некоторых членов b
, но как это сделать? В конце концов, это A
, а не B
, поэтому даже не слышал об этих членах, не говоря уже о возможности их хранения.
B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
//b2 now contains a mixture of b1 and b2!
Вы можете подумать, что b2
будет копией b1
впоследствии. Но, увы, это не так! Если вы проверите его, вы обнаружите, что b2
- это франкенштейновское существо, сделанное из некоторых кусков b1
(куски, которые B
наследует от A
), и некоторые фрагменты b2
(куски что только B
содержит). Ой!
Что случилось? Ну, C ++ по умолчанию не обрабатывает операторы присваивания как virtual
. Таким образом, строка a_ref = b1
вызовет оператор присваивания A
, а не номер B
. Это связано с тем, что для не виртуальных функций объявленный тип (который является A&
) определяет, какая функция вызывается, в отличие от фактического типа (который был бы B
, поскольку a_ref
ссылается на экземпляр B
). Теперь оператор присваивания A
явно знает только о членах, объявленных в A
, поэтому он будет копировать только те, оставляя члены, добавленные в B
без изменений.
Присвоение только части объекта обычно имеет мало смысла, но, к сожалению, C ++ не предусматривает встроенного способа запретить это. Вы можете, однако, бросить свои собственные. Первый шаг - сделать оператор присваивания виртуальным . Это гарантирует, что он всегда является оператором присваивания фактического типа, который вызывается, а не объявленным типом. Второй шаг - использовать dynamic_cast
, чтобы убедиться, что назначенный объект имеет совместимый тип. Третий шаг - выполнить фактическое присвоение в члене (protected!) assign()
, так как B
assign()
, вероятно, захочет использовать A
's assign()
для копирования A
членов .
class A {
public:
virtual A& operator= (const A& a) {
assign(a);
return *this;
}
protected:
void assign(const A& a) {
// copy members of A from a to this
}
};
class B : public A {
public:
virtual B& operator= (const A& a) {
if (const B* b = dynamic_cast<const B*>(&a))
assign(*b);
else
throw bad_assignment();
return *this;
}
protected:
void assign(const B& b) {
A::assign(b); // Let A's assign() copy members of A from b to this
// copy members of B from b to this
}
};
Обратите внимание, что для чистого удобства B
operator=
ковариантно переопределяет возвращаемый тип, поскольку он знает, что он возвращает экземпляр B
.
derived
может быть присвоено коду, ожидающему значение base
, или любая производная ссылка может использоваться в качестве базовой ссылки. Я хотел бы видеть язык с системой типов, которая затрагивает обе концепции отдельно. Существует много случаев, когда производная ссылка должна быть заменяемой для базовой ссылки, но производные экземпляры не должны подставляться под базовые; есть также много случаев, когда экземпляры должны быть конвертируемыми, но ссылки не должны подставляться.
– supercat
12 August 2013 в 17:11
Итак ... Почему потерять полученную информацию плохо? ... потому что автор производного класса, возможно, изменил представление таким образом, что отсечение дополнительной информации изменяет значение, представляемое объектом. Это может произойти, если производный класс, если используется для кэширования представления, более эффективного для определенных операций, но дорогого для преобразования обратно в базовое представление.
Также подумал, что кто-то должен также упомянуть, что вам следует делать, чтобы избежать нарезка ... Получите копию стандартов кодирования C ++, 101 правила и рекомендации.
Он предлагает несколько сложный шаблон, чтобы полностью решить проблему: иметь защищенный экземпляр копии, защищенный чистый виртуальный DoClone и публичный клон с утверждением, которое скажет вам если (далее) производный класс не смог правильно выполнить DoClone. (Метод Clone делает правильную глубокую копию полиморфного объекта.)
Вы также можете пометить конструктор копирования в явном виде базы, который позволяет явно нарезать, если это необходимо.
Третий матч в google для «C ++ slicing» дает мне эту статью в Википедии http://en.wikipedia.org/wiki/Object_slicing и этот (нагретый, но первые несколько сообщений определяют проблему ): http://bytes.com/forum/thread163565.html
Таким образом, это когда вы назначаете объект подкласса суперклассу. Суперкласс ничего не знает о дополнительной информации в подклассе и не имеет места для его хранения, поэтому дополнительная информация получает «отрезанный».
Если эти ссылки не дают достаточной информации для «хороший ответ», пожалуйста, отредактируйте свой вопрос, чтобы сообщить нам, что еще вы ищете.
class A
{
int x;
};
class B
{
B( ) : x(1), c('a') { }
int x;
char c;
};
int main( )
{
A a;
B b;
a = b; // b.c == 'a' is "sliced" off
return 0;
}
, когда объект производного класса присваивается объекту базового класса, дополнительные атрибуты объекта производного класса вырезаются (отбрасываются) из объекта базового класса.
class Base {
int x;
};
class Derived : public Base {
int z;
};
int main()
{
Derived d;
Base b = d; // Object Slicing, z of d is sliced off
}
Проблема нарезки является серьезной, поскольку это может привести к повреждению памяти, и очень сложно гарантировать, что программа не пострадает от нее. Чтобы разработать его из языка, классы, поддерживающие наследование, должны быть доступны только по ссылке (не по значению). Язык программирования D имеет это свойство.
Рассмотрим класс A и класс B, полученный из A. Повреждение памяти может произойти, если в A-части есть указатель p и экземпляр B, который указывает p на дополнительные данные B , Затем, когда дополнительные данные удаляются, p указывает на мусор.
Derived
неявно конвертируется в Base
.) Это, очевидно, противоречит принципу открытого закрывания и большому обслуживанию бремя.
– j_random_hacker
24 October 2012 в 13:30
Если у вас есть базовый класс A
и производный класс B
, вы можете сделать следующее.
void wantAnA(A myA)
{
// work with myA
}
B derived;
// work with the object "derived"
wantAnA(derived);
Теперь для метода wantAnA
нужна копия derived
, Однако объект derived
не может быть полностью скопирован, так как класс B
может изобретать дополнительные переменные-члены, которые не находятся в его базовом классе A
.
Поэтому, чтобы вызвать wantAnA
, компилятор будет «срезать» все дополнительные члены производного класса. Результатом может быть объект, который вы не хотите создавать, потому что
A
(все особые поведения класс B
теряется). wantAnA
(как следует из названия!) Хочет A
, то это то, что он получает. И экземпляр A
, будет, uh, вести себя как A
. Как это удивительно?
– fgp
22 January 2013 в 18:39
derived
с типом A
. Неявное кастинг всегда является источником неожиданного поведения на C ++, потому что часто бывает трудно понять, как локально это происходило при произведении.
– pqnet
7 August 2014 в 00:15