我有以下代码
$accountNumber = substr( str_shuffle( md5( time() ) ), 0, $aclenth );
$accountNumber = 'CYB-' . strtoupper( $accountNumber );
这给了我以下输出:
#include <iostream>
using namespace std;
class B{
int i;
public:
B(){
cout << "Constructing B\n";
}
void print(){
cout << "Printing from B with size : "<<sizeof(*this)<<endl;
}
};
class D:public B{
int i;
public:
D(){
cout << "Constructing D\n";
}
void print(){
cout << "Printing from D with size : "<<sizeof(*this)<<endl;
}
};
int main(){
B b;
b.print();
D d;
d.print();
D* dp;
dp->print();
}
因此,当您创建指向派生类的指针时,它是不是首先创建基类的实例?我不认为它是真的,因为D类的大小是证明。但它甚至没有调用基类构造函数。谁能解释一下呢?
答案 0 :(得分:5)
指针不会创建任何内容。指针只是指针 - 包含地址的标量对象。您有责任将指针指向内存中的正确位置。
在您的示例中,指针Dim result As Integer = 0
Dim i, ladderVal, LadderCount, size, valCount As Integer
ladderVal = 0
LadderCount = 0
size = A.Length
If size > 0 Then
For i = 1 To size - 1
If LadderCount = 0 Then
LadderCount += 1
ladderVal = A(i)
Else
If A(i) = ladderVal Then
LadderCount += 1
Else
LadderCount -= 1
End If
End If
Next
valCount = 0
For i = 0 To size - 1
If A(i) = ladderVal Then
valCount += 1
End If
Next
If valCount <= size / 2 Then
result = 0
Else
LadderCount = 0
For i = 0 To size - 1
If A(i) = ladderVal Then
valCount -= 1
LadderCount += 1
End If
If LadderCount > (LadderCount + 1) / 2 And (valCount > (size - (i + 1)) / 2) Then
result += 1
End If
Next
End If
End If
Return result
未初始化。你从来没有把它指向任何地方,所以它没有任何意义。您尝试调用dp
会产生未定义的行为。故事结束。
答案 1 :(得分:3)
现在你的指针根本没有初始化,所以尝试使用它会产生未定义的行为。尝试类似:
D *dp = new D;
dp->print();
delete dp;
或者做得更好,比如:
std::unique_ptr<D> dp = std::make_unique<D>();
dp->print();
... unique_ptr
会在超出范围时自动删除D
。
但是,请注意,您已将print
定义为非虚函数,因此调用的函数将取决于所使用的指针(或引用)的类型, not 它所引用的对象的类型。此外,您还没有定义虚拟dtor。
因此,如果您要做类似的事情:
B *p = std::make_unique<D>();
p->print(); // would invoke B::print, even though the object is a D
...当它超出范围时,它将被错误地销毁,因此你会得到未定义的行为。要更正此问题,您需要将B更改为以下内容:
class B{
int i;
public:
B(){
cout << "Constructing B\n";
}
virtual void print(){
cout << "Printing from B with size : "<<sizeof(*this)<<endl;
}
virtual ~B() = default;
};
执行此操作时,答案为“是” - 当您创建派生对象时,它将首先调用基类的ctor,然后调用派生类的ctor。当派生对象被销毁时,这是相反的:首先调用派生类的dtor,然后当它完成时,将执行基类的dtor。
答案 2 :(得分:3)
它在派生类之前构造基类。你的输出反映了这个。看看这个
//Constructs Base class
Constructing B
//Constructs Derived class
Constructing D
//Prints from derived
Printing from D with size : 8
您的代码在不调用构造函数的情况下两次打印Printing from D with size : 8
的原因是您的代码永远不会创建D
的第二个实例。
D* d;
^^^^ Declares a pointer to a D, Does not create a D!
当您致电d->print();
时,它是未定义的行为,因为d
未指向D
的实例。最后,您的代码打印在编译时确定的值(sizeof(D)
是编译时间值),并且不会触及代码运行的this
指针。
请参阅sizeof
here的文档。
答案 3 :(得分:2)
您可以使用强大的多态为Base
指针指定一个Derived
对象。这是可能的,因为Derived
实现了Base
包含的所有内容。因此,隐含Derived
基础在其自己的实例化期间实例化Base
。
class Base
{
public:
Base()
{}
}
class Derived : public Base
{
public:
Derived()
{}
}
Derived *derived = new Derived();
Base *base = derived;