220 7527 <CAPBZbvz1o_NKd7S8xL5E3-EV8oh4ezcc7kZio38bnDNWayEyKg@mail.gmail.com> article
Path: news.gmane.org!not-for-mail
From: "Billy O'Neal" <billy.oneal@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Fixing the private method issue
Date: Tue, 29 Oct 2013 21:12:10 -0700
Lines: 274
Approved: news@gmane.org
Message-ID: <CAPBZbvz1o_NKd7S8xL5E3-EV8oh4ezcc7kZio38bnDNWayEyKg@mail.gmail.com>
References: <d5cd9fa5-ac2f-465b-b92d-cf2a35607245@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=089e0160c35ee1f99e04e9ed8bd5
X-Trace: ger.gmane.org 1383106365 6621 80.91.229.3 (30 Oct 2013 04:12:45 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Wed, 30 Oct 2013 04:12:45 +0000 (UTC)
To: std-proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDKLBLVE6ADBBQUOYKJQKGQESOWFQGQ@isocpp.org Wed Oct 30 05:12:52 2013
Return-path: <std-proposals+bncBDKLBLVE6ADBBQUOYKJQKGQESOWFQGQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ob0-f200.google.com ([209.85.214.200])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDKLBLVE6ADBBQUOYKJQKGQESOWFQGQ@isocpp.org>)
	id 1VbN9H-0004wd-Tz
	for gclcip-std-proposals@m.gmane.org; Wed, 30 Oct 2013 05:12:52 +0100
Original-Received: by mail-ob0-f200.google.com with SMTP id uy5sf2553635obc.11
        for <gclcip-std-proposals@m.gmane.org>; Tue, 29 Oct 2013 21:12:51 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:list-post:list-help:list-archive:list-subscribe
         :list-unsubscribe:content-type;
        bh=YN/zPGhZBmrrru0ECHP/x0aQzogKlh7QM3hOac74wf0=;
        b=EvHBf2nGDVxbeuIUbplmFvEF18xEIp+944sELsO1KKR9dotPGj45efzS2Zk7577Rnz
         w1bDkuL5mOKZ4GfhudFe+OAR/SMoXPposeZnSOGsSoMtroTuaE0Yn7qNSJOTG1W2awLb
         FF04mnwJaXOTPZ1qquSra7sbq3N171GqYNdA66y1b5zzv90szm4AAMDzhyBGdFCBT3yV
         hfU/fQ9lOyNhc7WZCFvtp93Pgu8j/rMvSXOyThd08PV93kCZfenYidGWcIHwGLTYaxkg
         kFdvyEMOwZbLApLzoPfmjZBUTazhzMQ79FIJGVRvMsyOxNZTGGX7vNg/puedXeJ6RPcH
         VUDw==
X-Gm-Message-State: ALoCoQl9bIU6LysJ9ktcQjSES0JzV6DaA75sec3vcQhvhdW9ScO1fNRJQAI4/KYy55PWec4/xMEu
X-Received: by 10.50.17.101 with SMTP id n5mr488311igd.2.1383106370907;
        Tue, 29 Oct 2013 21:12:50 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.182.29.229 with SMTP id n5ls179015obh.66.gmail; Tue, 29 Oct
 2013 21:12:50 -0700 (PDT)
X-Received: by 10.182.106.4 with SMTP id gq4mr2642273obb.4.1383106370396;
        Tue, 29 Oct 2013 21:12:50 -0700 (PDT)
Original-Received: from mail-ob0-x22e.google.com (mail-ob0-x22e.google.com [2607:f8b0:4003:c01::22e])
        by mx.google.com with ESMTPS id ii9si13858841obc.115.2013.10.29.21.12.50
        for <std-proposals@isocpp.org>
        (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
        Tue, 29 Oct 2013 21:12:50 -0700 (PDT)
Received-SPF: pass (google.com: domain of billy.oneal@gmail.com designates 2607:f8b0:4003:c01::22e as permitted sender) client-ip=2607:f8b0:4003:c01::22e;
Original-Received: by mail-ob0-f174.google.com with SMTP id vb8so920398obc.19
        for <std-proposals@isocpp.org>; Tue, 29 Oct 2013 21:12:50 -0700 (PDT)
X-Received: by 10.182.66.164 with SMTP id g4mr2441446obt.47.1383106370204;
 Tue, 29 Oct 2013 21:12:50 -0700 (PDT)
Original-Received: by 10.182.87.37 with HTTP; Tue, 29 Oct 2013 21:12:10 -0700 (PDT)
In-Reply-To: <d5cd9fa5-ac2f-465b-b92d-cf2a35607245@isocpp.org>
X-Original-Sender: billy.oneal@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of billy.oneal@gmail.com designates 2607:f8b0:4003:c01::22e as
 permitted sender) smtp.mail=billy.oneal@gmail.com;       dkim=pass
 header.i=@gmail.com;       dmarc=pass (p=NONE dis=NONE) header.from=gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:7527
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/7527>

--089e0160c35ee1f99e04e9ed8bd5
Content-Type: text/plain; charset=ISO-8859-1

> One other use of this feature could be to add a backdoor for unit tests.

Unit tests that test non-public data are bad (brittle) unit tests. Break up
those classes! :)

For most cases where these bits matter you can define a static non-member
non-friend function in a file somewhere, and have your member function
implementations call these non-members.

Another mitigation is to put your "private member functions" into another
class, and declare that class a friend. You still leak the one symbol, but
that's comparatively minor:

http://ideone.com/K9m0Fz

#include <iostream>
class PublicClass
{
 friend class PublicClassImpl;
 int idx;
public:
 PublicClass() : idx (42) {}
 void DoWork();
};

// In the implementation file:
class PublicClassImpl
{
public:
    static void DoWorkImpl(PublicClass& target);
};

void PublicClass::DoWork()
{
 PublicClassImpl::DoWorkImpl(*this);
}

void PublicClassImpl::DoWorkImpl(PublicClass& target)
{
 std::cout << "Index is currently " << target.idx++ << std::endl;
}

// Example Use:
int main() {
 PublicClass pc;
 pc.DoWork();
 pc.DoWork();
 return 0;
}

Billy O'Neal
https://github.com/BillyONeal/ <https://bitbucket.org/BillyONeal/>
http://stackoverflow.com/users/82320/billy-oneal
Malware Response Instructor - BleepingComputer.com


On Tue, Oct 29, 2013 at 8:39 PM, <fmatthew5876@gmail.com> wrote:

> There is one major wart in C++ class design, and that is with private
> member functions required to be in the class definition.
>
> This has a number of problems:
> 1) Changing the private method's signature or adding/removing private
> methods requires everyone including the header to recompile. This is a huge
> problem for large projects with long recompilation times.
> 2) file static / anonymous namespace definitions in the .cc file cannot be
> used in the private method's signature. Anything used in the signature must
> be at least forward declared in the header, adding more symbol pollution.
> 3) For shared library interfaces, the private methods are extra
> unnecessary symbols that have to be managed.
> 4) Private method signatures or even the existence of private methods can
> depend on the underlying implementation. If the class has multiple
> implementations (e.g. different platforms), #defines and other conditional
> compilation mechanisms are required in the header file.
> 5) Its just bad encapsulation. Callers don't need to know anything about
> the functions which implement the class behavior.
>
> The only private declarations that should be required in the header are
> declarations required by the compiler. I believe all of those are:
> 1) Private data members (sizeof())
> 2) Private virtual methods (for inheriting)
> 3) Private non-virtual methods called by inline functions.
>
> One way to do this would be to extend the friend feature. We could define
> friend functions within the body of member functions. It might look like
> this:
>
> //foo.hh
>
> class Foo {
>   public:
>     void doWork();
>   private:
>     int _f;
> }
>
> //foo.cc
> static void doWorkHelper(Foo* f) {
>   doSomethingWith(f->_f);
> };
>
> void Foo::doWork() {
>   friend void doWorkHelper(Foo*);
>
>   doWorkHelper(this);
> }
>
> This has potential for abuse of course, but it would finally allow us to
> limit the list of declarations in the class definition to the bare minimum
> required by the compiler. When it comes to defining interfaces, less is
> always more.
> One other use of this feature could be to add a backdoor for unit tests.
>
> Thoughts?
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

-- 

--- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--089e0160c35ee1f99e04e9ed8bd5
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>&gt; One other use of this feature could be to add a =
backdoor for unit tests.</div><div>=A0</div><div>Unit tests that test non-p=
ublic data are bad (brittle) unit tests. Break up those classes! :)</div><d=
iv>

=A0</div><div>For most cases where these bits matter you can define a stati=
c non-member non-friend function in a file somewhere, and have your member =
function implementations call these non-members.</div><div>=A0</div><div>An=
other mitigation is to put your &quot;private member functions&quot; into a=
nother class, and declare that class a friend. You still leak the one symbo=
l, but that&#39;s comparatively minor:</div>

<div>=A0</div><div><a href=3D"http://ideone.com/K9m0Fz">http://ideone.com/K=
9m0Fz</a></div><div>=A0</div><div><font face=3D"courier new,monospace">#inc=
lude &lt;iostream&gt;</font></div><div><font face=3D"courier new,monospace"=
>class PublicClass<br>

{<br>=A0friend class PublicClassImpl;<br>=A0int idx;<br>public:<br>=A0Publi=
cClass() : idx (42) {}<br>=A0void DoWork();<br>};</font></div><div>=A0</div=
><div><font face=3D"courier new,monospace">// In the implementation file:<b=
r>class PublicClassImpl<br>

{<br>public:<br>=A0=A0=A0 static void DoWorkImpl(PublicClass&amp; target);<=
br>};</font></div><div><font face=3D"Courier New"></font>=A0</div><div><fon=
t face=3D"courier new,monospace">void PublicClass::DoWork()<br>{<br>=A0Publ=
icClassImpl::DoWorkImpl(*this);<br>

}</font></div><div>=A0</div><div><font face=3D"courier new,monospace">void =
PublicClassImpl::DoWorkImpl(PublicClass&amp; target)<br>{<br>=A0std::cout &=
lt;&lt; &quot;Index is currently &quot; &lt;&lt; target.idx++ &lt;&lt; std:=
:endl;<br>

}</font></div><div>=A0</div><div><font face=3D"courier new,monospace">// Ex=
ample Use:</font></div><div><font face=3D"courier new,monospace">int main()=
 {<br>=A0PublicClass pc;<br>=A0pc.DoWork();<br>=A0pc.DoWork();<br>=A0return=
 0;<br>}</font></div>

<div><font face=3D"Courier New"></font>=A0</div><div>Billy O&#39;Neal</div>=
<div class=3D"gmail_extra"><div><div dir=3D"ltr"><div><a href=3D"https://bi=
tbucket.org/BillyONeal/" target=3D"_blank">https://github.com/BillyONeal/</=
a></div>

<div><a href=3D"http://stackoverflow.com/users/82320/billy-oneal" target=3D=
"_blank">http://stackoverflow.com/users/82320/billy-oneal</a></div><div>Mal=
ware Response Instructor - BleepingComputer.com</div></div></div>
<br><br><div class=3D"gmail_quote">On Tue, Oct 29, 2013 at 8:39 PM,  <span =
dir=3D"ltr">&lt;<a href=3D"mailto:fmatthew5876@gmail.com" target=3D"_blank"=
>fmatthew5876@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-colo=
r:rgb(204,204,204);border-left-width:1px;border-left-style:solid">

<div dir=3D"ltr">There is one major wart in C++ class design, and that is w=
ith private member functions required to be in the class definition.<div><b=
r></div><div>This has a number of problems:</div><div>1) Changing the priva=
te method&#39;s signature or adding/removing private methods requires every=
one including the header to recompile. This is a huge problem for large pro=
jects with long recompilation times.</div>

<div>2) file static / anonymous namespace definitions in the .cc file canno=
t be used in the private method&#39;s signature. Anything used in the signa=
ture must be at least forward declared in the header, adding more symbol po=
llution.</div>

<div>3) For shared library interfaces, the private methods are extra unnece=
ssary symbols that have to be managed.</div><div>4) Private method signatur=
es or even the existence of private methods can depend on the underlying im=
plementation. If the class has multiple implementations (e.g. different pla=
tforms), #defines and other conditional compilation mechanisms are required=
 in the header file.</div>

<div>5) Its just bad encapsulation. Callers don&#39;t need to know anything=
 about the functions which implement the class behavior.</div><div><br></di=
v><div>The only private declarations that should be required in the header =
are declarations required by the compiler. I believe all of those are:</div=
>

<div>1) Private data members (sizeof())</div><div>2) Private virtual method=
s (for inheriting)</div><div>3) Private non-virtual methods called by inlin=
e functions.</div><div><br></div><div>One way to do this would be to extend=
 the friend feature. We could define friend functions within the body of me=
mber functions. It might look like this:</div>

<div><br></div><div>//foo.hh</div><div><br></div><div>class Foo {<br>=A0 pu=
blic:</div><div>=A0 =A0 void doWork();</div><div>=A0 private:</div><div>=A0=
 =A0 int _f;</div><div>}</div><div><br></div><div>//foo.cc</div><div>static=
 void doWorkHelper(Foo* f) {</div>

<div>=A0 doSomethingWith(f-&gt;_f);<br>};</div><div><br></div><div>void Foo=
::doWork() {<br>=A0 friend void doWorkHelper(Foo*);</div><div><br></div><di=
v>=A0 doWorkHelper(this);</div><div>}</div><div><br></div><div>This has pot=
ential for abuse of course, but it would finally allow us to limit the list=
 of declarations in the class definition to the bare minimum required by th=
e compiler. When it comes to defining interfaces, less is always more.</div=
>

<div>One other use of this feature could be to add a backdoor for unit test=
s.</div><div><br></div><div>Thoughts?</div></div><span class=3D"HOEnZb"><fo=
nt color=3D"#888888">

<p></p>

-- <br>
=A0<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></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 unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--089e0160c35ee1f99e04e9ed8bd5--

.
