Topic: Virtual Static Data Members, draft rv.1


Author: Brent Friedman <fourthgeek@gmail.com>
Date: Sat, 26 Jan 2013 00:43:01 -0800 (PST)
Raw View
------=_Part_123_2715994.1359189781998
Content-Type: multipart/alternative;
 boundary="----=_Part_124_13698890.1359189781998"

------=_Part_124_13698890.1359189781998
Content-Type: text/plain; charset=ISO-8859-1

I've made some significant changes to the proposal 'virtual data members'
proposed several day ago and more strictly formalized its exact semantics.

Feedback is greatly appreciated!

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



------=_Part_124_13698890.1359189781998
Content-Type: text/html; charset=ISO-8859-1

I've made some significant changes to the proposal 'virtual data members' proposed several day ago and more strictly formalized its exact semantics.<div><br></div><div>Feedback is greatly appreciated!</div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_124_13698890.1359189781998--
------=_Part_123_2715994.1359189781998
Content-Type: text/html; charset=US-ASCII; name=VirtualStatic.html
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=VirtualStatic.html
X-Attachment-Id: 5fa5bd11-9071-4cba-9ca5-a6cae882b53f
Content-ID: <5fa5bd11-9071-4cba-9ca5-a6cae882b53f>

<html><head><title>Untitled document</title><style type=3D"text/css">@impor=
t url('https://themes.googleusercontent.com/fonts/css?kit=3DwAPX1HepqA24RkY=
W1AuHYA');ol{margin:0;padding:0}.c8{max-width:468pt;background-color:#fffff=
f;padding:72pt 72pt 72pt 72pt}.c9{font-size:14pt}.c7{font-weight:bold}.c6{t=
ext-align:right}.c1{font-family:"Calibri"}.c3{font-size:18pt}.c2{height:11p=
t}.c4{text-align:center}.c10{font-size:24pt}.c5{font-style:italic}.c0{direc=
tion:ltr}.title{padding-top:24pt;line-height:1.15;text-align:left;color:#00=
0000;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt=
}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;=
font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}l=
i{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-siz=
e:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;te=
xt-align:left;color:#000000;font-size:18pt;font-family:"Arial";font-weight:=
bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:lef=
t;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding=
-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#666=
666;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}=
h4{padding-top:12pt;line-height:1.15;text-align:left;color:#666666;font-sty=
le:italic;font-size:11pt;font-family:"Arial";padding-bottom:2pt}h5{padding-=
top:11pt;line-height:1.15;text-align:left;color:#666666;font-size:10pt;font=
-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;lin=
e-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:10p=
t;font-family:"Arial";padding-bottom:2pt}</style></head><body class=3D"c8">=
<p class=3D"c0 c6"><span>Document Number: xxxx=3D13xxxx</span></p><p class=
=3D"c6 c0"><span>Date: 2013-02-1</span></p><p class=3D"c6 c0"><span>Project=
: Programming Language C++</span></p><p class=3D"c6 c0"><span>Reply-to: Bre=
nt Friedman; brent &lt;dot&gt; friedman &lt;at&gt; gearboxsoftware &lt;dot&=
gt; com</span></p><p class=3D"c2 c0 c4"><span></span></p><p class=3D"c2 c4 =
c0"><span></span></p><p class=3D"c2 c4 c0"><span></span></p><p class=3D"c2 =
c4 c0"><span></span></p><p class=3D"c2 c4 c0"><span></span></p><p class=3D"=
c4 c0"><span class=3D"c10">Virtual Static Data Members</span></p><p class=
=3D"c4 c0"><span class=3D"c9">Revision 1</span></p><p class=3D"c2 c4 c0"><s=
pan></span></p><p class=3D"c2 c4 c0"><span></span></p><p class=3D"c2 c4 c0"=
><span></span></p><p class=3D"c2 c4 c0"><span></span></p><p class=3D"c2 c0"=
><span></span></p><p class=3D"c0"><span class=3D"c3">I. Table of Contents</=
span></p><p class=3D"c0"><span class=3D"c3">xxxx</span></p><p class=3D"c2 c=
0"><span class=3D"c3"></span></p><p class=3D"c0"><span class=3D"c3">II. Int=
roduction</span></p><p class=3D"c0"><span>Virtual static data members repre=
sent a new storage class which allows for storing data values per type rath=
er than per instance. Virtual static data presents opportunities for memory=
 reduction, performance enhancement, improved optimization opportunities, a=
nd improved ease of use when compared to other implementations. Virtual fun=
ctions paired with static data are the closest existing language mechanism.=
</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span class=
=3D"c3">III. Motivation</span></p><p class=3D"c0"><span>Though C++ supports=
 RTTI for certain basic type information, it is not uncommon that a program=
mer desires for types to have additional, user-defined properties that can =
be accessed and even modified at runtime. For any nontrivial set of require=
ments this will often mean creating something like </span><span class=3D"c1=
">class ClassInfo</span><span>&nbsp;to represent type information and forci=
ng each object to store a </span><span class=3D"c1">ClassInfo*</span><span>=
.. However, the C++ standard already requires the compiler to know the dynam=
ic type of an object and how to access that object&rsquo;s virtual function=
s. This is typically implemented as a per-object pointer to a virtual funct=
ion table. So by adding </span><span class=3D"c1">ClassInfo*</span><span>&n=
bsp;to the mix we now have two pointers that both represent the object&rsqu=
o;s type under different contexts. Yet, even the </span><span class=3D"c1">=
ClassInfo*</span><span>&nbsp;solution gets brittle and complex if you need =
to subclass </span><span class=3D"c1">ClassInfo</span><span>, requiring pot=
entially dangerous casts. Finally, it would be yet more difficult and likel=
y macro-laden work to build a framework that allows the </span><span class=
=3D"c1">ClassInfo</span><span>&nbsp;object to be accessed statically as in =
</span><span class=3D"c1">static_assert(MyClass::ClassInfo.xyz, &ldquo;...&=
rdquo;)</span><span>. By allowing arbitrary user-defined data to be placed =
into the compiler&rsquo;s existing bookkeeping structures we can reduce obj=
ect size, expand flexibility and intelligibility when defining types, and m=
ay improve cache locality. When compared with virtual functions, virtual da=
ta is much easier to optimize because the compiler cannot easily guarantee =
that a virtual function might not modify global state and can certainly not=
 inline the function. Virtual static data, on the other hand, has exactly d=
efined behavior because you are simply accessing a value at a dynamically-c=
alculated memory location. </span></p><p class=3D"c2 c0"><span></span></p><=
p class=3D"c0"><span>It is expected that this proposal will be most useful =
to library implementers and those requiring absolute speed with certain spe=
cific features of polymorphic objects.</span></p><p class=3D"c2 c0"><span><=
/span></p><p class=3D"c0"><span class=3D"c3">IV. Impact on the Standard</sp=
an></p><p class=3D"c0"><span>This proposal adds a new storage class specifi=
er which is only valid on class member data. It allows for data members to =
be both implicitly declared and implicitly defined which makes it an intere=
sting special case for the one definition rule. Existing code will not be i=
mpacted.</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><spa=
n class=3D"c3">V. Technical Specifications</span></p><p class=3D"c0"><span =
class=3D"c9">Overview</span></p><p class=3D"c0"><span>Any member data decla=
red both static and virtual causes each subclass to implicitly declare an i=
dentically matching static data member. If no definition for an implicitly =
declared virtual static data member is provided, that data member is implic=
itly defined to</span><span class=3D"c5">&nbsp;inherit</span><span>&nbsp;th=
e definition used in the parent class. For most purposes, including lifetim=
e and initialization, virtual static is identical to static. &nbsp;Example:=
</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span class=
=3D"c1">struct Base</span></p><p class=3D"c0"><span class=3D"c1">{</span></=
p><p class=3D"c0"><span class=3D"c1">&nbsp; //int Something; // each object=
 has an int</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; virtual sta=
tic int Etc; //each *class* has an int</span></p><p class=3D"c0"><span clas=
s=3D"c1">&nbsp; virtual static size_t Count; //each class can count the num=
ber of instances created</span></p><p class=3D"c0"><span class=3D"c1">&nbsp=
; Base() &nbsp;{ &nbsp;++Count;}//Increments Base::CreationCount</span></p>=
<p class=3D"c0"><span class=3D"c1">};</span></p><p class=3D"c0"><span class=
=3D"c1">size_t Base::Count=3D0;</span></p><p class=3D"c0"><span class=3D"c1=
">size_t Base::Etc=3D0;</span></p><p class=3D"c2 c0"><span class=3D"c1"></s=
pan></p><p class=3D"c0"><span class=3D"c1">struct Special : public Base</sp=
an></p><p class=3D"c0"><span class=3D"c1">{</span></p><p class=3D"c0"><span=
 class=3D"c1">&nbsp;//Special::Count and Special::Etc are implicitly declar=
ed</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; Special() { &nbsp;++=
Count; } //Increments Special::CreationCount </span></p><p class=3D"c0"><sp=
an class=3D"c1">};</span></p><p class=3D"c0"><span class=3D"c1">//Special::=
Count is not defined in any T.U. so it implicitly inherits the definition o=
f Base::Count</span></p><p class=3D"c0"><span class=3D"c1">int Special::Etc=
(15);</span></p><p class=3D"c2 c0"><span class=3D"c1"></span></p><p class=
=3D"c0"><span class=3D"c1">int main()</span></p><p class=3D"c0"><span class=
=3D"c1">{</span></p><p class=3D"c0"><span class=3D"c1">assert(Base::Count=
=3D=3D0,&ldquo;Objects of class Base should not exist before main&rdquo;);<=
/span></p><p class=3D"c2 c0"><span class=3D"c1"></span></p><p class=3D"c0">=
<span class=3D"c1">Base* b =3D new Base;</span></p><p class=3D"c0"><span cl=
ass=3D"c1">Base::Count; //=3D=3D1</span></p><p class=3D"c0"><span class=3D"=
c1">b-&gt;Count; // =3D=3D 1, accesses static Base::Count</span></p><p clas=
s=3D"c0"><span class=3D"c1">b-&gt;Etc; // =3D=3D0, accesses static Base::Et=
c</span></p><p class=3D"c2 c0"><span class=3D"c1"></span></p><p class=3D"c0=
"><span class=3D"c1">Base* s =3D new Special;</span></p><p class=3D"c0"><sp=
an class=3D"c1">b-&gt;Count; //=3D=3D2</span></p><p class=3D"c0"><span clas=
s=3D"c1">s-&gt;Count; // =3D=3D1, accesses static Special::Count</span></p>=
<p class=3D"c0"><span class=3D"c1">s-&gt;Etc; //=3D=3D15, accesses static S=
pecial::Etc</span></p><p class=3D"c0"><span class=3D"c1">}</span></p><p cla=
ss=3D"c2 c0"><span class=3D"c1"></span></p><p class=3D"c2 c0"><span class=
=3D"c1"></span></p><p class=3D"c0"><span>Although similar functionality can=
 be implemented in the existing language, the simplicity of the above appro=
ach is hard to deny. As already demonstrated under </span><span class=3D"c5=
">Motivation</span><span>, storing a separate structure of class informatio=
n does not solve this problem elegantly. Now compare the virtual function a=
pproach:</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><spa=
n class=3D"c1">struct Base</span></p><p class=3D"c0"><span class=3D"c1">{</=
span></p><p class=3D"c0"><span class=3D"c1">&nbsp; static int Etc;</span></=
p><p class=3D"c0"><span class=3D"c1">&nbsp; static size_t Count;</span></p>=
<p class=3D"c0"><span class=3D"c1">&nbsp; Base() &nbsp;{ &nbsp;++Count;}</s=
pan></p><p class=3D"c0"><span class=3D"c1">&nbsp; virtual size_t&amp; GetCo=
unt(){ return Count; }</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; =
virtual int&amp; GetEtc(){ return Etc;}</span></p><p class=3D"c0"><span cla=
ss=3D"c1">};</span></p><p class=3D"c0"><span class=3D"c1">size_t Base::Coun=
t=3D0;</span></p><p class=3D"c0"><span class=3D"c1">size_t Base::Etc=3D0;</=
span></p><p class=3D"c2 c0"><span class=3D"c1"></span></p><p class=3D"c0"><=
span class=3D"c1">struct Special : public Base</span></p><p class=3D"c0"><s=
pan class=3D"c1">{</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; stat=
ic int Etc;</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; static size=
_t Count;</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; Special() { &=
nbsp;++Count; }</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; virtual=
 size_t&amp; GetCount(){ return Count; }</span></p><p class=3D"c0"><span cl=
ass=3D"c1">&nbsp; virtual int&amp; GetEtc(){return Etc;}</span></p><p class=
=3D"c0"><span class=3D"c1">};</span></p><p class=3D"c0"><span class=3D"c1">=
size_t Special::Count=3DBase::Count;</span></p><p class=3D"c0"><span class=
=3D"c1">int Special::Etc=3D15;</span></p><p class=3D"c2 c0"><span></span></=
p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span>For even modera=
tely sized class hierarchies, this duplication becomes a maintenance diffic=
ulty that will usually be solved with macros. And yet for all of that effor=
t we do not get great performance since in general </span><span class=3D"c1=
">GetCount()</span><span>&nbsp;and </span><span class=3D"c1">GetEtc()</span=
><span>&nbsp;could execute arbitrary code which makes it difficult to optim=
ize their callsite. With virtual data, not only does the compiler have stri=
cter guarantees about the operation being performed, but we also omit the o=
verhead of the virtual function call (which in general cannot be inlined), =
reduce complexity, and make the code less brittle. This performance differe=
nce may be significant when a virtual function call in a tight loop is repl=
aced with accessing static virtual data.</span></p><p class=3D"c2 c0"><span=
></span></p><p class=3D"c0"><span class=3D"c9">Implementation-Specific Cons=
iderations</span></p><p class=3D"c0"><span>Although the language standard d=
oes not require the existence of a virtual function table, it is generally =
expected that virtual function support is implemented as such. Any compiler=
 which did not implement a virtual function table would still have some way=
 of identifying the dynamic type of an object and could use the same mechan=
ism for finding virtual static data. In a sense, this language extension wo=
uld convert the virtual function table from an array of function pointers t=
o an arbitrary compiler-defined structure. Alignment requirements on types =
would need to be upheld but the compiler would be free to rearrange and pac=
k the table so as to produce minimum necessary structure size.</span></p><p=
 class=3D"c2 c0"><span></span></p><p class=3D"c0"><span>In certain environm=
ents it may be expected that the vtable resides in read only memory. Althou=
gh the language cannot make any guarantees to support this, individual comp=
iler toolchains could support </span><span class=3D"c1">#pragma</span><span=
>s</span><span>&nbsp;or compiler switches to produce a warning if this expe=
ctation could not be met. Declaring virtual static data as constexpr will p=
rovide sufficient information for the compiler to put virtual static data i=
n ROM when it can be supported.</span></p><p class=3D"c2 c0"><span></span><=
/p><p class=3D"c0"><span class=3D"c9">Multiple inheritance</span></p><p cla=
ss=3D"c2 c0"><span></span></p><p class=3D"c0"><span>Consider the standard e=
xample of a diamond inheritance pattern with </span><span class=3D"c1">B</s=
pan><span>&nbsp;and </span><span class=3D"c1">C</span><span>&nbsp;inheritin=
g from </span><span class=3D"c1">A</span><span>, and </span><span class=3D"=
c1">D</span><span>&nbsp;inheriting from </span><span class=3D"c1">B</span><=
span>&nbsp;and </span><span class=3D"c1">C</span><span>.</span></p><p class=
=3D"c2 c0"><span></span></p><p class=3D"c0"><span>If </span><span class=3D"=
c1">A</span><span>&nbsp;declares a virtual static data member </span><span =
class=3D"c1">v</span><span>&nbsp;then this does not on its own create any a=
mbiguities because each class receives its own version of the virtual stati=
c data. Class </span><span class=3D"c1">D</span><span>&nbsp;will not receiv=
e two copies here, only one. Therefore v is dynamically resolved to </span>=
<span class=3D"c1">D::v</span><span>&nbsp;when accessed via class member sy=
ntax.</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span>H=
owever, with these data also inheriting their definition from parent classe=
s, the definition of </span><span class=3D"c1">D::v</span><span>&nbsp;becom=
es ambiguous if </span><span class=3D"c1">D</span><span>&nbsp;does not defi=
ne </span><span class=3D"c1">v</span><span>. Due to this ambiguity, </span>=
<span class=3D"c1">D </span><span>must define </span><span class=3D"c1">v</=
span><span>&nbsp;even if </span><span class=3D"c1">v</span><span>&nbsp;is n=
ever odr-used.</span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0=
"><span class=3D"c9">Definition of virtual static data</span></p><p class=
=3D"c0"><span>To ease implementation and reduce impact on the standard, vir=
tual static data members retain the property of static data members that th=
e definition occurs separately from the declaration.</span></p><p class=3D"=
c2 c0"><span></span></p><p class=3D"c0"><span>Since virtual static data cou=
ld be used to represent an interface, it may be useful to define the data m=
ember as pure virtual which forces the data member to both remain uninitial=
ized and make it illegal to odr-use. The natural syntax would be e.g. </spa=
n><span class=3D"c1">virtual static int x=3D0;</span><span>&nbsp;with </spa=
n><span class=3D"c1">=3D0</span><span>&nbsp;meaning pure virtual. However, =
this example illustrates how easily the </span><span class=3D"c1">=3D0 </sp=
an><span>syntax could be misunderstood. Instead, it is proposed that </span=
><span class=3D"c1">=3Ddelete</span><span>&nbsp;be used to mark virtual sta=
tic data as pure virtual. Additionally, the </span><span class=3D"c1">=3Dde=
fault </span><span>syntax is optionally proposed as a mechanism for forcing=
 a virtual static data member to use the same definition as used by the cla=
ss that originally declared the virtual static data member. Neither </span>=
<span class=3D"c1">=3Ddefault</span><span>&nbsp;nor </span><span class=3D"c=
1">=3Ddelete </span><span>are considered vital to this proposal but could h=
elp to expand the usefulness of this feature.</span></p><p class=3D"c2 c0">=
<span></span></p><p class=3D"c0"><span class=3D"c3">VI. Proposed Text</span=
></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span class=3D"c7"=
>&sect;</span><span class=3D"c7">&nbsp;3.2 </span></p><p class=3D"c0"><span=
>3.[...(see] 9.4.2.1, [12.1...]</span></p><p class=3D"c2 c0"><span></span><=
/p><p class=3D"c0"><span class=3D"c7">&sect; 5.2.5</span></p><p class=3D"c0=
"><span>4. [If E2 is a static data member ... the named member of the class=
] if the data member is non-virtual or the named member of the dynamic type=
 of E1 if the data member is virtual. [The type of E1.E2 is T.]</span></p><=
p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span class=3D"c7">&sect=
; 7.1.1 </span></p><p class=3D"c0"><span>(append </span><span class=3D"c1">=
virtual</span><span>)</span></p><p class=3D"c0"><span>1. [...static or exte=
rn] and </span><span class=3D"c1">virtual</span><span>, if present, must ap=
pear with </span><span class=3D"c1">static</span><span>. </span><span class=
=3D"c1">Thread_local</span><span>&nbsp;and </span><span class=3D"c1">virtua=
l</span><span>&nbsp;may not appear together in a storage-class-specifier. [=
If thread_local] or </span><span class=3D"c1">virtual</span><span>&nbsp;[ap=
pear ...]</span></p><p class=3D"c0"><span>12. The </span><span class=3D"c1"=
>virtual</span><span>&nbsp;storage class specifier may only be applied to s=
tatic data members. See &sect;9.4.2.1.</span></p><p class=3D"c2 c0"><span><=
/span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span class=
=3D"c7">&sect; 9.4.2 &nbsp; </span></p><p class=3D"c0"><span>1.</span><span=
>{Append}</span><span class=3D"c5">&nbsp;</span><span>If a static data memb=
er </span><span class=3D"c1">s</span><span>&nbsp;within class </span><span =
class=3D"c1">X</span><span>&nbsp;is declared </span><span class=3D"c1">virt=
ual</span><span>&nbsp;then each class inheriting from </span><span class=3D=
"c1">X</span><span>&nbsp;implicitly declares a static data member with the =
same name, access rules, and </span><span class=3D"c5">decl-specifier</span=
><span>&nbsp;as s. A subclass shall not explicitly declare a virtual static=
 data member that is declared by a base class.</span></p><p class=3D"c2 c0"=
><span></span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c2 c0"><s=
pan></span></p><p class=3D"c0"><span class=3D"c7 c5">New section </span></p=
><p class=3D"c0"><span class=3D"c7">&sect; </span><span class=3D"c7">9.4.2.=
1 Virtual static members</span></p><p class=3D"c0"><span>1</span><span>. A =
class which explicitly declares a virtual static data member shall also exp=
licitly define the member (as in &nbsp;&sect;9.4.2 #2). If the program prov=
ides an explicit definition for a virtual static data member instance then =
that definition is used. Otherwise, the instance implicitly inherits its de=
finition from the parent class from which the member was inherited. If mult=
iple potential definitions are inherited, the program shall explicitly prov=
ide a definition or be ill-formed. [</span><span class=3D"c5">Example:</spa=
n></p><p class=3D"c0 c2"><span></span></p><p class=3D"c0"><span class=3D"c1=
">struct Base { virtual static int v;};</span></p><p class=3D"c0"><span cla=
ss=3D"c1">struct DerivedA : public Base{ }; </span></p><p class=3D"c0"><spa=
n class=3D"c1">struct DerivedB : public DerivedA{ };</span></p><p class=3D"=
c0"><span class=3D"c1">int Base::v=3D0; //Base::v is explicitly declared an=
d explicitly defined</span></p><p class=3D"c0"><span class=3D"c1">//Derived=
A::v is implicitly declared and implicitly defined as 0, inherited from Bas=
e::v</span></p><p class=3D"c0"><span class=3D"c1">int DerivedB::v(5); //Der=
ived::v is implicitly declared and explicitly defined</span></p><p class=3D=
"c2 c0"><span class=3D"c1"></span></p><p class=3D"c0"><span class=3D"c1">in=
t main()</span></p><p class=3D"c0"><span class=3D"c1">{</span></p><p class=
=3D"c0"><span class=3D"c1">&nbsp;//Base::v=3D=3D0, DerivedA::v=3D=3D0, Deri=
vedB::v=3D=3D5</span></p><p class=3D"c0"><span class=3D"c1">&nbsp;Base* b =
=3D new DerivedB;</span></p><p class=3D"c0"><span class=3D"c1">&nbsp;b-&gt;=
v; //=3D5</span></p><p class=3D"c0"><span class=3D"c1">&nbsp;++Base::v;</sp=
an></p><p class=3D"c0"><span class=3D"c1">&nbsp;//Base::v=3D=3D1, DerivedA:=
:v=3D=3D0, DerivedB::v=3D5</span></p><p class=3D"c0"><span class=3D"c1">}</=
span></p><p class=3D"c2 c0"><span></span></p><p class=3D"c0"><span>-- </spa=
n><span class=3D"c5">end example</span><span>]</span></p><p class=3D"c2 c0"=
><span></span></p><p class=3D"c0"><span>2. In addition to normal initializa=
tion syntax (&sect;8.5), instances of virtual static data members may also =
be defined using a </span><span class=3D"c5">virtual-data-initializer</span=
><span>.</span></p><p class=3D"c0"><span>&nbsp;</span><span class=3D"c5">vi=
rtual-data-initializer:</span></p><p class=3D"c0"><span class=3D"c1">&nbsp;=
 &nbsp;=3Ddelete</span></p><p class=3D"c0"><span class=3D"c1">&nbsp; &nbsp;=
=3Ddefault</span></p><p class=3D"c0"><span class=3D"c1">=3Ddelete</span><sp=
an>&nbsp;marks the data member as a pure virtual. Instances which are pure =
are never initialized. Programs attempting to odr-use pure virtual data are=
 ill-formed. It is unspecified whether memory is reserved for instances of =
pure virtual data.</span></p><p class=3D"c0"><span class=3D"c1">=3Ddefault<=
/span><span>&nbsp;causes an implicitly declared instance of the data member=
 to use the same definition used by the base class that explicitly declared=
 the member [Note -- That is, &lsquo;reset to original&rsquo;].</span></p><=
/body></html>
------=_Part_123_2715994.1359189781998--

.